【问题标题】:Control closing of popup for QML ComboBox with checkboxes使用复选框控制 QML ComboBox 弹出窗口的关闭
【发布时间】:2017-07-13 04:51:42
【问题描述】:

我正在构建一个带有复选框的自定义 QML ComboBox。它显示一切都很好,但我无法控制弹出关闭事件。

我希望组合框弹出窗口保持打开状态,以便我可以检查多个项目。并且仅当我在父母外部单击或单击逃生时才关闭。 目前,只要我检查一个项目,它就会关闭。

我正在使用 CheckDelegate,因此我可以覆盖组合框弹出窗口的外观。但是它不等待让我一次检查多个项目。

这是我的自定义组合框示例代码

import QtQuick 2.7
import QtQuick.Controls 2.1

ComboBox {
id: control

property alias combo_box_model: control.model
property string combo_box_displayText: control.displayText
property var combo_box_height

model: combo_box_model

delegate: CheckDelegate {
    id: checkbox_control

    width: control.width
    contentItem: Text {
        leftPadding: checkbox_control.indicator.width + control.leftPadding

        text: modelData
        font: control.font
        elide: Text.ElideRight
        verticalAlignment: Text.AlignVCenter
    }
    highlighted: control.highlightedIndex === index
//        checked: combo_box_model.isChecked(index)

    indicator: Rectangle {
            implicitWidth: 26
            implicitHeight: 26
            x: control.leftPadding
            anchors.verticalCenter: parent.verticalCenter

            radius: 3
            color: "transparent"
            border.color: checkbox_control.down ? "#17a81a" : "#21be2b"

            Rectangle {
                width: 14
                height: 14
                x: 6
                y: 6
                radius: 2
                color: checkbox_control.down ? "#17a81a" : "#21be2b"
                visible: checkbox_control.checked
            }
    }

//        onClicked: {
//            combo_box_model.setChecked(index, checked)
//        }

}

contentItem: Text {
    leftPadding: 0
    rightPadding: control.indicator.width + control.spacing

    text: control.displayText
    font: control.font
    horizontalAlignment: Text.AlignLeft
    verticalAlignment: Text.AlignVCenter
    elide: Text.ElideRight
}

popup: Popup {
    id: checkbox_popup
    y: control.height - 1
    width: control.width
    implicitHeight: contentItem.implicitHeight
    padding: 1

    contentItem: ListView {
        clip: true
        implicitHeight: combo_box_height ? combo_box_height : contentHeight
        model: control.popup.visible ? control.delegateModel : null
        currentIndex: control.highlightedIndex

        ScrollIndicator.vertical: ScrollIndicator { }
    }
}

}

对于组合框弹出窗口 (checkbox_popup),我尝试将 closePolicy 设置为 NoAutoClose,但没有成功。

所以我觉得在 CheckDelegate 的某个地方我需要捕获关闭事件左右并处理它。但不确定究竟是如何或我错过了什么? 就 QML 而言,这是一个新手。

【问题讨论】:

    标签: checkbox combobox qml qt5


    【解决方案1】:

    我同意 Mark 的观点:ComboBox 旨在在关闭时显示单个选定的项目,因此进行多项选择没有意义。

    但我也同意无论如何尝试它都很有趣。 :D 这是一种利用ComboBox relies on the delegate being an AbstractButton:

    import QtQuick 2.6
    import QtQuick.Controls 2.0
    
    ApplicationWindow {
        id: window
        visible: true
        width: 640
        height: 480
    
        ComboBox {
            id: comboBox
            model: ListModel {
                ListElement {
                    name: "A"
                    checked: false
                }
                ListElement {
                    name: "B"
                    checked: false
                }
                ListElement {
                    name: "C"
                    checked: false
                }
            }
    
            delegate: Item {
                width: parent.width
                implicitHeight: checkDelegate.implicitHeight
    
                CheckDelegate {
                    id: checkDelegate
                    width: parent.width
                    text: model.name
                    highlighted: comboBox.highlightedIndex === index
                    checked: model.checked
                    onCheckedChanged: model.checked = checked
                }
            }
        }
    }
    

    【讨论】:

    • 太棒了!谢谢米奇。这行得通。好把戏!!现在正如@Mark 提到的,如果 ComboBox 用于单选,我可能需要重新考虑一下。我希望我可以在组合框显示 (contentItem) 中将选择显示为省略的文本。
    【解决方案2】:

    这似乎是对 Combobox 委托的相当复杂的覆盖,而且可能不是正确的方法。

    CheckDelegate 继承 ItemDelegate,它负责您试图避免的行为(单击后关闭弹出窗口)。如果您使用不同的项目覆盖委托,例如Rectangle、MouseArea 或 Item,则自动关闭行为将消失。

    此外,组合框设计为一次选择一个 currentItem。当 currentItem 更改时,它通常返回单个 currentIndex。要改变这种行为,我觉得是一场艰苦的斗争,你最好简单地使用带有列表视图的弹出窗口,而不是组合框。

    但是,您的挑战看起来很有趣,所以这里是修复组合框的一种方法:

    ComboBox {
        id: control
    
        property bool forceOpen: false
    
        model: ["alpha", "beta", "gamma"]
    
        delegate: CheckDelegate {
            id: checkbox_control
    
            width: control.width
            contentItem: Text {
                leftPadding: checkbox_control.indicator.width + control.leftPadding
    
                text: modelData
                font: control.font
                elide: Text.ElideRight
                verticalAlignment: Text.AlignVCenter
            }
            highlighted: control.highlightedIndex === index
    
            indicator: Rectangle {
                    implicitWidth: 26
                    implicitHeight: 26
                    x: control.leftPadding
                    anchors.verticalCenter: parent.verticalCenter
    
                    radius: 3
                    color: "transparent"
                    border.color: checkbox_control.down ? "#17a81a" : "#21be2b"
    
                    Rectangle {
                        width: 14
                        height: 14
                        x: 6
                        y: 6
                        radius: 2
                        color: checkbox_control.down ? "#17a81a" : "#21be2b"
                        visible: checkbox_control.checked
                    }
            }
        }
    
        popup: Popup {
    
            id: checkbox_popup
            y: control.height - 1
            width: control.width
            implicitHeight: contentItem.implicitHeight
            padding: 1
    
            contentItem: ListView {
                clip: true
                implicitHeight: contentHeight
                model: control.popup.visible ? control.delegateModel : null
                currentIndex: control.highlightedIndex
    
                ScrollIndicator.vertical: ScrollIndicator { }
            }
    
            onClosed: if (control.forceOpen) open()
        }
    
        background: Rectangle {
            implicitWidth: 120
            implicitHeight: 40
    
            border.width: !control.editable && control.visualFocus ? 2 : 0
            visible: !control.flat || control.down
    
            MouseArea {
                anchors.fill: parent
                onClicked: {
                    if (control.popup.visible) {
                        control.forceOpen = false
                        control.popup.close()
                    } else {
                        control.forceOpen = true
                        control.popup.open()
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 感谢@mark 的回答。是的,我确实读过委托需要是一个 ItemDelegate,但我认为会有某种方法可以禁用弹出窗口关闭。我尝试了您的解决方案,但尝试将其作为点击后的钩子保持打开,会添加闪烁效果。
    • @pappachino 哦,对了,我想知道它是否会闪烁,但是当我在 Windows 上尝试时似乎没有。哦,好吧。
    • 我看到弹出窗口正在使用 control.delegateModel - 该属性在哪里?我在任何地方都找不到任何文档。
    • @DavidJ 我认为它没有记录。通常这表明我们不应该搞砸它!您可以在源代码中查看它并了解如何使用它code.woboq.org/qt5/qtquickcontrols2/src/quicktemplates2/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多