使用复选框控制QML ComboBox的弹出窗口关闭

时间:2017-07-13 04:51:43

标签: checkbox combobox qml qt5

我正在使用复选框构建自定义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的某个地方我需要捕获close事件或者处理它。但不确定我到底是怎么回事? 就QML而言,相当新手。

2 个答案:

答案 0 :(得分:0)

这似乎是对Combobox代表的一个复杂的重写,也许不是正确的方法。

CheckDelegate继承了ItemDelegate,它负责您试图避免的行为(单击后关闭弹出窗口)。如果您使用其他项目覆盖代理,例如Rectangle,MouseArea或Item,然后自动关闭行为就会消失。

此外,组合框设计为一次选择一个currentItem。当currentItem发生变化时,它通常会返回一个currentIndex。为了改变这种行为,我觉得这是一场艰难的斗争,你可能更好的只是使用一个带有listview的弹出窗口,而不是一个Combobox。

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

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()
                }
            }
        }
    }
}

答案 1 :(得分:0)

我同意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
            }
        }
    }
}