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

【写在前面】

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

其代码如下:

qml 复制代码
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 中为:
qml 复制代码
Flickable {
    ...
    onMovementStarted: {
        for (let key in contentItem.children) {
            let item = contentItem.children[key];
            if (item.objectName === "__ComboBox__")
                item.popup.close();
        }
    }

    ComboBox {
        ...
        objectName: "__ComboBox__"
    }
}
  • Qt6 中为:
qml 复制代码
Flickable {
    ...
    onMovementStarted: {
        for (let item of contentItem.children) {
            if (item.objectName === "__ComboBox__")
                item.popup.close();
        }
    }

    ComboBox {
        ...
        objectName: "__ComboBox__"
    }
}

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

修复后的效果如下:


【结语】

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

qml 复制代码
Popup {
    Popup {
        ...
    }
}

而修复思路也大致相似。

相关推荐
Xam_d_LM1 小时前
【Qt】在 Qt Creator 中使用图片资源方法(含素材网站推荐)
开发语言·c++·qt·ui·贴图·qt5
何曾参静谧2 小时前
「QT」几何数据类 之 QSizeF 浮点型尺寸类
开发语言·qt
机器视觉知识推荐、就业指导2 小时前
Qt中自定义CustomDoubleSpinBox
开发语言·qt
重生之我是数学王子2 小时前
C++基础 抽象类 类模板 STL库 QT环境
开发语言·c++·qt
青山的青衫3 小时前
【Qt】Macbook M1下载安装
开发语言·qt
小丑西瓜66619 小时前
qt ui设计案例--登录界面
qt·ui·c/c++·qss
内蒙深海大鲨鱼1 天前
qt之ui开发
数据库·qt·ui
我有一颗薄荷糖1 天前
Qt--命令行终端程序开发
开发语言·数据库·qt
码农客栈1 天前
qt QTextFrame详解
qt
小狮子安度因1 天前
Qt文件系统-二进制文件读写
qt