QML ComboBox项目DropDownMenu样式

时间:2014-11-23 14:02:45

标签: c++ qt user-interface qml

我想在我的项目中使用ComboBox类型。是否可以更改下拉菜单的外观(颜色,形状,文本样式),还是需要使用矩形,ListView和其他类型的组合?

以下代码应用自定义项,但未为下拉菜单定义修改,该菜单仍为灰色:

ComboBox {
    currentIndex: 2
    activeFocusOnPress: true
    style: ComboBoxStyle {
        id: comboBox
        background: Rectangle {
            id: rectCategory
            radius: 5
            border.width: 2
            color: "#fff"

            Image {
                source: "pics/corner.png"
                anchors.bottom: parent.bottom
                anchors.right: parent.right
                anchors.bottomMargin: 5
                anchors.rightMargin: 5
            }
        }
        label: Text {
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
            font.pointSize: 15
            font.family: "Courier"
            font.capitalization: Font.SmallCaps
            color: "black"
            text: control.currentText
        }
    }

    model: ListModel {
        id: cbItems
        ListElement { text: "Banana" }
        ListElement { text: "Apple" }
        ListElement { text: "Coconut" }
    }
    width: 200
}

4 个答案:

答案 0 :(得分:14)

当前的公共API不允许自定义下拉菜单hereQt 5.4,即Styles 1.3,刚刚介绍了一些属性来自定义字体和文本(文档here),但仍无法公开访问下拉自定义。

此外,链接中提供的示例不适用于较新版本的Qt。这是我用Qt 5.3,Qt 5.4和Qt 5.5测试的修改版本(记得在导入中添加import QtQuick.Controls.Private 1.0):

ComboBox {
    id: box
    currentIndex: 2
    activeFocusOnPress: true
    style: ComboBoxStyle {
        id: comboBox
        background: Rectangle {
            id: rectCategory
            radius: 5
            border.width: 2
            color: "#fff"
        }
        label: Text {
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
            font.pointSize: 15
            font.family: "Courier"
            font.capitalization: Font.SmallCaps
            color: "black"
            text: control.currentText
        }

        // drop-down customization here
        property Component __dropDownStyle: MenuStyle {
            __maxPopupHeight: 600
            __menuItemType: "comboboxitem"

            frame: Rectangle {              // background
                color: "#fff"
                border.width: 2
                radius: 5
            }

            itemDelegate.label:             // an item text
                Text {
                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignHCenter
                font.pointSize: 15
                font.family: "Courier"
                font.capitalization: Font.SmallCaps
                color: styleData.selected ? "white" : "black"
                text: styleData.text
            }

            itemDelegate.background: Rectangle {  // selection of an item
                radius: 2
                color: styleData.selected ? "darkGray" : "transparent"
            }

            __scrollerStyle: ScrollViewStyle { }
        }

        property Component __popupStyle: Style {
            property int __maxPopupHeight: 400
            property int submenuOverlap: 0

            property Component frame: Rectangle {
                width: (parent ? parent.contentWidth : 0)
                height: (parent ? parent.contentHeight : 0) + 2
                border.color: "black"
                property real maxHeight: 500
                property int margin: 1
            }

            property Component menuItemPanel: Text {
                text: "NOT IMPLEMENTED"
                color: "red"
                font {
                    pixelSize: 14
                    bold: true
                }
            }

            property Component __scrollerStyle: null
        }
    }

    model: ListModel {
        id: cbItems
        ListElement { text: "Banana" }
        ListElement { text: "Apple" }
        ListElement { text: "Coconut" }
    }
    width: 200
}     

此处为__dropDownStyle分配了MenuStyle类型。这种类型的一些属性是自定义的,以获得所需的样式,特别是itemDelegate(定义组合框内项目的外观)和frame(整体背景)。有关更多详细信息,请参阅链接的MenuStyle API。总体结果:

enter image description here

请注意,此方法在Windows和Android上完美运行,而在OSX上,代码完全被忽略。可以检查Qt安装中的qml样式文件(搜索qml/QtQuick/Controls/Styles/Desktop之类的子路径)以查看w.r.t的更改。 Windows并尝试调整提供的解决方案。这部分由读者完成。

答案 1 :(得分:5)

非常感谢!我通过下一个代码解决了这个问题:

Item {
id: app
width: 200
height: 150

ListModel{
    id: dataModel
    ListElement{ name: "Day" }
    ListElement{ name: "Week" }
    ListElement{ name: "Month" }
    ListElement{ name: "Year" }
}

Button {
    id: comboButton
    width: parent.width
    height: parent.height / 5
    checkable: true

    style: ButtonStyle {
       background: Rectangle {
           color: control.pressed ? "#888" : "#fff"
           smooth: true
           radius: 5
           border.width: 2

           Image {
               source: "pics/corner.png"
               anchors.bottom: parent.bottom
               anchors.right: parent.right
               anchors.bottomMargin: 5
               anchors.rightMargin: 5
           }
       }
       label: Text {
            renderType: Text.NativeRendering
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
            font.family: "Courier"
            font.capitalization: Font.SmallCaps
            font.pointSize: 15
            color: "black"
            text: "Day"
        }
    }
    onVisibleChanged: {
        if(!visible)
            checked = false
    }
}

TableView {
    id: tableView
    height: 120
    width: parent.width
    anchors.bottom: parent.bottom
    highlightOnFocus: true
    headerVisible: false
    visible: comboButton.checked ? true : false

    TableViewColumn {
        role: "name"
    }
    model: dataModel

    itemDelegate: Item {
        Rectangle {
            color: styleData.selected  ? "#888" : "#fff"
            height: comboButton.height - 0.5
            border.width: 0.5
            width: parent.width

            Text {
                renderType: Text.NativeRendering
                anchors.verticalCenter: parent.verticalCenter
                anchors.horizontalCenter: parent.horizontalCenter
                font.family: "Courier"
                font.capitalization: Font.SmallCaps
                font.pointSize: 15
                color: "black"
                elide: styleData.elideMode
                text: styleData.value
            }
        }
    }

    rowDelegate: Item {
        height: comboButton.height - 0.5
    }

    onClicked: {
       comboButton.checked = false
       tableView.selection.clear()
    }
}
} 

enter image description here

答案 2 :(得分:1)

使用当前Qt(截至2020年),可以通过指定backgroundcontentItemindicatordelegate来自定义ComboBox: https://doc.qt.io/qt-5/qtquickcontrols2-customize.html#customizing-combobox

答案 3 :(得分:0)

我一直在使用这样的方法,但它们在focus管理和z-index管理方面存在很多限制。

我最终得到了ComboBox的实现,它由两部分组成:一个实际放在某处的标题和一个动态创建的下拉组件。后者包括一个覆盖所有内容的Item(以及拦截鼠标活动)和一个小心地位于标题下方的下拉列表。

此处包含的代码非常庞大,因此您可以查看详细信息in my blogpost with all the code