Qml 中的那些坑(七)—ComboBox嵌入Popup时,滚动内容超过其可见区域不会关闭ComboBox弹窗

【写在前面】

最近在写信息提交 ( 表单 ) 的窗口时发现一个奇怪的 BUG:

Qml 中的那些坑(七)---ComboBox嵌入Popup时,滚动内容超过其可见区域不会关闭ComboBox弹窗

其代码如下:

import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Window 2.15  Window {     width: 640     height: 480     visible: true     title: qsTr("Hello World")      Button{         text: "open"         onClicked: popup.open();     }      Popup {         id: popup         width: 400         height: 200         anchors.centerIn: parent         clip: true         closePolicy: Popup.CloseOnPressOutside         background: Rectangle { color: "#80800000" }         contentItem: Flickable {             id: flickable             clip: true             topMargin: 10             contentWidth: implicitWidth             contentHeight: 500             ScrollBar.vertical: ScrollBar { width: 14 }             /*onMovementStarted: {                 for (let key in contentItem.children) {                     let item = contentItem.children[key];                     if (item.objectName === "__ComboBox__")                         item.popup.close();                 }             }*/              ComboBox {                 width: 160                 height: 40                 objectName: "__ComboBox__"                 model: ["aaaaaa", "bbbbbb", "cccccc", "dddddd"]             }         }     } }  

可以看到,当 ComboBox 嵌入 Popup 时,点开 ComboBox,然后滚动内容超过其可见区域并不会关闭 ComboBox 弹窗,并且会超出其 父 Popup 范围。


【正文开始】

实际上,这是几乎存在在 Qt 所有版本 ( Qt5 ~ Qt6 ) 的 BUG,猜测其主要原因为弹窗无法对内部嵌套弹窗进行裁剪,因为此弹窗 ( Popup ) 并非真正的窗口 ( Window )

该 BUG 我已报告给官方:https://bugreports.qt.io/browse/QTBUG-130960?filter=-2

不过,在官方修复的版本出来之前,我实现的改动较小的修复办法为:

  • Qt5 中为:
Flickable {     ...     onMovementStarted: {         for (let key in contentItem.children) {             let item = contentItem.children[key];             if (item.objectName === "__ComboBox__")                 item.popup.close();         }     }      ComboBox {         ...         objectName: "__ComboBox__"     } } 
  • Qt6 中为:
Flickable {     ...     onMovementStarted: {         for (let item of contentItem.children) {             if (item.objectName === "__ComboBox__")                 item.popup.close();         }     }      ComboBox {         ...         objectName: "__ComboBox__"     } } 

只需要在当视图由于用户交互或生成的 flick() 而开始移动时,关闭掉 ComboBox 的弹窗即可。

修复后的效果如下:

Qml 中的那些坑(七)---ComboBox嵌入Popup时,滚动内容超过其可见区域不会关闭ComboBox弹窗


【结语】

最后,要说明并非只有本文中的例子会有该 BUG,所有形如下面的代码都可能出现。

Popup {     Popup {         ...     } } 

而修复思路也大致相似。

发表评论

相关文章