如何将 QML Combox 的大小调整为其较大元素的宽度?

How to size a QML Combox to the width of its bigger element?

我有一个 ComboBox,在纯 QML 代码中定义为一个组件(因此没有后端),我想将其宽度自动设置为其最宽的元素。目前,它采用最后选定元素的宽度,因此其弹出窗口无法正确显示其内容。

这是一个 mcve

Window {
    id: mainWindow
    title: "Test"
    width: 500
    height: 200
    modality: Qt.WindowModal
    flags: Qt.Dialog | Qt.WindowSystemMenuHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint
    //color: "#E3E3E3"


    GridLayout {
        anchors.fill: parent
        anchors.margins: 25
        columnSpacing: 10
        rowSpacing: 10
        columns: 2

        Label {
            text: "Foo"
        }

        Loader {
            id: loadCombo1
            sourceComponent: niceComboBox
            Binding {
                target: loadCombo1.item
                property: "model"
                value: [{'value': "none",'text': "None"}, 
                {'value': "medium",'text': "Some medium length text"}, 
                {'value': "long",'text':   "A pretty very long string that shouldn't be hidden"}]
            }

        }
    }

    Component {
        id: niceComboBox

        ComboBox {
            id: control
            delegate: ItemDelegate { // requiert QuickControls 2.2
                width: control.width
                contentItem: Text {
                    text: modelData.text
                    anchors.verticalCenter: parent.verticalCenter
                }
                highlighted: control.highlightedIndex === index
            }

            contentItem: Text {

                text: control.model ? control.model[control.currentIndex].text : ""
                anchors.verticalCenter: parent.verticalCenter
                leftPadding: 10
                rightPadding: 10
                topPadding: 5
                bottomPadding: 5
                verticalAlignment: Text.AlignVCenter

            }

            FontMetrics {
                id: fontMetric
                font.family: control.contentItem.font.family

            }
            Component.onCompleted: {
                //computeWidth();
            }

            Behavior on model {
                ScriptAction {
                    script: computeWidth()

                }
            }

            function computeWidth() {
                if (control.model == null) {
                    return;
                }

                var longest = "";
                for (var i = 0; i < model.length; i++) {
                    var txt = model[i].text;
                    if (txt.length > longest.length)
                        longest = txt;
                }
                var pwidth = fontMetric.boundingRect(longest).width;
                pwidth += control.contentItem.rightPadding + control.contentItem.leftPadding;
                pwidth += control.indicator.width
                width = pwidth;
            }

        }
    }
}

问题是当执行 Component.onCompleted 时,加载程序尚未指定模型。并且无法正确处理宽度的计算。

我尝试添加 Behavior on model 脚本来检测模型中的变化,但它没有做任何事情。

我该怎么办? 谢谢

我仅限于这些版本:QtQuick 2.9 和 QtQuick.Controls 2.2

[编辑] 我合并了@Mitch 的评论。

在 Qt 6 中,您可以使用 implicitContentWidthPolicy 属性:

import QtQuick.Controls

ApplicationWindow {
    width: 640
    height: 480
    visible: true

    ComboBox {
        anchors.centerIn: parent
        implicitContentWidthPolicy: ComboBox.WidestTextWhenCompleted
        model: ["String", "A longer string", "A very, very long string"]
    }
}

我想到了这个解决方案:

import QtQuick 2.9
import QtQuick.Controls 2.2

ComboBox {
    id: control

    model: []

    delegate: ItemDelegate { // requiert QuickControls 2.2
        width: control.width
        contentItem: Text {
            text: modelData.text
            anchors.verticalCenter: parent.verticalCenter
        }
        highlighted: control.highlightedIndex === index
    }

    contentItem: Text {

        text: control.model[control.currentIndex].text
        anchors.verticalCenter: parent.verticalCenter
        leftPadding: 10
        rightPadding: 10
        topPadding: 5
        bottomPadding: 5
        verticalAlignment: Text.AlignVCenter
    }

    FontMetrics {
        id: fontMetric
        font.family: control.contentItem.font.family

    }

    Binding on implicitWidth {
        value: computeWidth(model)
    }
    
    popup.implicitWidth: computeWidth(model)


    function computeWidth(mdl) {
        if (mdl == null) {
            return;
        }



        var longest = "";
        for (var i = 0; i < mdl.length; i++) {
            var txt = mdl[i].text;
            if (txt.length > longest.length)
                longest = txt;
        }
        var pwidth = fontMetric.boundingRect(longest).width;
        pwidth += control.contentItem.rightPadding + control.contentItem.leftPadding;
        pwidth += control.indicator.width

        return pwidth;
    }

}