Checkbox 使用复选框控制QML组合框弹出窗口的关闭

Checkbox 使用复选框控制QML组合框弹出窗口的关闭,checkbox,combobox,qml,qt5,Checkbox,Combobox,Qml,Qt5,我正在构建一个带有复选框的自定义QML组合框。它显示得很好,但我无法控制弹出关闭事件 我希望组合框弹出窗口保持打开状态,以便我可以检查多个项目。只有当我在父对象外单击或按escape键时,才能关闭。 目前,只要我检查一个项目,它就会关闭 我正在使用CheckDelegate,以便覆盖组合框弹出窗口的外观。但是它不等待允许我一次检查多个项目 这是我的自定义组合框示例代码 import QtQuick 2.7 import QtQuick.Controls 2.1 ComboBox { id: c

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

我希望组合框弹出窗口保持打开状态,以便我可以检查多个项目。只有当我在父对象外单击或按escape键时,才能关闭。 目前,只要我检查一个项目,它就会关闭

我正在使用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\u popup),我尝试将closePolicy设置为NoAutoClose,但没有成功

因此,我觉得在CheckDelegate中的某个地方,我需要捕获关闭事件并处理它。但不确定我到底是怎么错过了什么?
就QML而言,这是一个相当新手。

这似乎是对Combobox委托的一个相当复杂的重写,可能不是正确的方法

CheckDelegate继承ItemDelegate,它负责您试图避免的行为(单击一次后关闭弹出窗口)。如果使用不同的项(例如矩形、鼠标区域或项)覆盖代理,则自动关闭行为将消失

此外,组合框设计为一次选择一个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()
                }
            }
        }
    }
}

我同意这里的标记:
组合框
意味着在关闭时显示一个选中的项目,所以有多个选择是没有意义的

但我也同意,不管怎样,尝试它是很有趣的D以下是一种利用以下事实的方法:


谢谢@mark的回答。是的,我确实读到代理需要是ItemDelegate,但我认为有某种方法可以禁用弹出关闭。我尝试了你的解决方案,但试图将其打开作为点击后挂钩,会增加闪烁效果。@pappachino哦,对了,我想知道它是否会闪烁,但当我在windows上尝试时,它似乎不会闪烁。哦,好吧。我看到弹出窗口正在使用control.delegateModel-该属性在哪里?我在任何地方都找不到它的任何文档。@DavidJ我想它没有文档。通常这意味着我们不应该搞砸它!您可以在源代码中看到它,并了解如何使用它!谢谢你,米奇。这很有效。好把戏!!现在正如@Mark提到的,如果ComboBox是用于单选的,我可能需要重新考虑一下。我希望我可以在组合框显示(contentItem)中将选择显示为省略文本。
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
            }
        }
    }
}