如何限制QML中ComboBox下拉列表的大小

How to limit the size of drop-down of a ComboBox in QML

我在 QML 中使用 ComboBox,当填充大量数据时,它超出了我的主要 windows 底部边界。通过谷歌搜索,我了解到 ComboBox 的下拉列表位于当前应用程序 window 的顶部,因此它不遵守其边界。

理想情况下,我希望 ComboBox 永远不会超出主要应用程序边界,但我在 documentation.

中找不到任何 属性

另一种方法是限制下拉列表中可见项目的数量,使其不超过给定 window 几何图形的 window 限制。我也无法在文档中找到它,而且我 运行 没有想法。

查看 ComboBox 源代码,弹出窗口是 Menu 类型,并且没有任何 属性 来限制其大小。此外,Menuz属性是infinite,即总是在上面。

如果你别无选择,只能使用 Qt 的 ComboBox,你可以创建两个模型,一个用于视觉目的,我称之为视觉模型,你将在你的 ComboBox 中显示它,另一个是完整的, 它将作为参考模型。您的 VisualModel 中的项目计数将等于您声明的某个 int 属性 maximumComboBoxItemsCount。你需要找到一种方法让 onHovered 在视觉模型中找到鼠标下的索引,如果它是 === to maximumComboBoxIemsCount 你做 visualModel.remove(0) et visualModel.add(referenceModel.get(maximum .. + 1) 并且您将需要另一个 属性 minimumComboBoxIemsCount,相同的逻辑但对于 Scroll Up ,我不知道它是否会起作用。但这是一个想法

我认为没有使用内置组件的解决方案,您应该创建自己的组合框。你可以从下面的代码开始。

ComboBox.qml

import QtQuick 2.0 

Item {
    id: comboBox

    property string initialText
    property int maxHeight
    property int selectedItem:0
    property variant listModel
    signal expanded
    signal closed
    //    signal sgnSelectedChoice(var choice)
    width: 100
    height: 40
    ComboBoxButton {
        id: comboBoxButton
        width: comboBox.width
        height: 40
        borderColor: "#fff"
        radius: 10
        margin: 5
        borderWidth: 2
        text: initialText
        textSize: 12

        onClicked: {
            if (listView.height == 0)
            {
                listView.height = Math.min(maxHeight, listModel.count*comboBoxButton.height)
                comboBox.expanded()
                source = "qrc:/Images/iconUp.png"
            }
            else
            {
                listView.height = 0
                comboBox.closed()
                source = "qrc:/Images/iconDown.png"
            }
        }
    }

    Component {
        id: comboBoxDelegate

        Rectangle {
            id: delegateRectangle
            width: comboBoxButton.width
            height: comboBoxButton.height
            color: "#00000000"
            radius: comboBoxButton.radius
            border.width: comboBoxButton.borderWidth
            border.color: comboBoxButton.borderColor



            Text {
                color: index == listView.currentIndex ? "#ffff00" : "#ffffff"
                anchors.centerIn: parent
                anchors.margins: 3
                font.pixelSize: 12
                text: value
                font.bold: true
            }


            MouseArea {
                anchors.fill: parent

                onClicked: {
                    listView.height = 0
                    listView.currentIndex = index
                    comboBox.selectedItem = index
                    tools.writePersistence(index,5)
                    comboBoxButton.text = value
                    comboBox.closed()
                }
            }
        }
    }

    ListView {
        id: listView
        anchors.top: comboBoxButton.bottom
        anchors.left: comboBoxButton.left
        width: parent.width
        height: 0
        clip: true
        model: listModel
        delegate: comboBoxDelegate
        currentIndex: selectedItem
    }
    onClosed:  comboBoxButton.source = "qrc:/Images/iconDown.png"
    Component.onCompleted: {
        var cacheChoice = tools.getPersistence(5);
        listView.currentIndex = tools.toInt(cacheChoice)
        selectedItem = listView.currentIndex
        comboBoxButton.text = cacheModel.get(selectedItem).value
    }
}

ComboBoxButton.qml

    import QtQuick 2.0 

Item {
    id: container
    signal clicked
    property string text
    property alias source : iconDownUp.source
    property string color: "#ffffff"
    property int textSize: 12
    property string borderColor: "#00000000"
    property int borderWidth: 0
    property int radius: 0
    property int margin: 0

    Rectangle {
        id: buttonRectangle
        anchors.fill: parent
        color: "#00000000"
        radius: container.radius
        border.width: container.borderWidth
        border.color: container.borderColor

        Image {
            id: image
            anchors.fill:  parent
            source: "qrc:/Images/buttonBackground.png"

            Image {
                id: iconDownUp
                source: "qrc:/Images/iconDown.png"
                sourceSize.height:20
                sourceSize.width: 20
                anchors.verticalCenter: parent.verticalCenter
            }
        }

        Text {
            id:label
            color: container.color
            anchors.centerIn: parent
            font.pixelSize: 10
            text: container.text
            font.bold: true
        }

        MouseArea {
            id: mouseArea;
            anchors.fill: parent
            onClicked: {
                container.clicked()
                buttonRectangle.state = "pressed"
                startTimer.start()
            }
        }
        Timer{
            id:startTimer
            interval: 200
            running: false;
            repeat: false
            onTriggered: buttonRectangle.state = ""
        }
        states: State {
            name: "pressed"
            when: mouseArea.pressed
            PropertyChanges { target: image; scale: 0.7 }
            PropertyChanges { target: label; scale: 0.7 }
        }

        transitions: Transition {
            NumberAnimation { properties: "scale"; duration: 200; easing.type: Easing.InOutQuad }
        }
    }
}

我在我的一些软件中使用过它,因此它可能无法工作"out of the box"。我是这样使用的:

ComboBox{
    id:cacheChoice
    initialText: "None"
    anchors.top: baseContainer.top
    anchors.topMargin: 2
    anchors.right: baseContainer.right
    maxHeight: 500
    listModel: cacheModel

    onExpanded: {
        cacheChoice.height = 500
    }

    onClosed: {
        cacheChoice.height = 20
    }
}

可以访问 ComboBoxStyle 组件中隐藏的 MenuStyle。在那里,您可以使用 MenuStyle 中的所有东西和隐藏的东西,包括它的最大高度。

事情大致是这样的。 不漂亮,但效果很好。

import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.3
import QtQuick.Window 2.2

ComboBox {
  id: comboBox

  style: ComboBoxStyle {

    // drop-down customization here
    property Component __dropDownStyle: MenuStyle {
      __maxPopupHeight: 400
      __menuItemType: "comboboxitem" //not 100% sure if this is needed
  }
}

由于它在我们的团队中引起了共鸣,这里是上述想法的更新版本。新版本会自动将大小限制为您的应用程序的大小。

ComboBox {
  id: root

  style: ComboBoxStyle {
    id: comboBoxStyle

    // drop-down customization here
    property Component __dropDownStyle: MenuStyle {
      __maxPopupHeight: Math.max(55, //min value to keep it to a functional size even if it would not look nice
                                 Math.min(400,
                                          //limit the max size so the menu is inside the application bounds
                                            comboBoxStyle.control.Window.height
                                          - mapFromItem(comboBoxStyle.control, 0,0).y
                                          - comboBoxStyle.control.height))
      __menuItemType: "comboboxitem" //not 100% sure if this is needed
    } //Component __dropDownStyle: MenuStyle
  } //style: ComboBoxStyle
} //ComboBox

如果您使用 Qt Quick Controls 2 中的组合框,这里是它的源代码:

https://github.com/qt/qtquickcontrols2/blob/5.12/src/imports/controls/ComboBox.qml

基于此,此行为覆盖可将高度限制在合理范围内:

    myComboBox.popup.contentItem.implicitHeight = Qt.binding(function () {
        return Math.min(250, myComboBox.popup.contentItem.contentHeight);
    });