Warm tip: This article is reproduced from stackoverflow.com, please click
c++ qml QT user-interface

QML ComboBox item DropDownMenu style

发布于 2020-03-29 21:03:29

I want to use the ComboBox type in my project. Is it possible to change the appearance of the drop-down menu (color, shape, text style) or do I need to use a combination of rectangles, ListViews and other types?

The following code applies customizations but no modification is defined for the drop-down menu which remains gray:

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
}
Questioner
otashlanov
Viewed
79
BaCaRoZzo 2016-01-21 20:56

The current public APIs does not allow customization of the drop-down menu as stated here. Qt 5.4, i.e. Styles 1.3, just introduced some properties to customize fonts and text (docs here) but still no public access to drop-down customization.

Also, the example provided in the link does not work with the newer versions of Qt. Here is a modified version I've tested with Qt 5.3, Qt 5.4 and Qt 5.5 (remember to add import QtQuick.Controls.Private 1.0 to the imports):

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
}     

Here __dropDownStyle is assigned with a MenuStyle type. Some properties of such type are customized to obtain the desired style, in particular itemDelegate (which defines the appearance of an item inside the combobox) and frame (overall background). Refer to the linked MenuStyle APIs for more details. Overall result:

enter image description here

Note that this approach does perfectly work on Windows and Android whereas on OSX the code is completely ignored. One can check the qml style file inside the Qt installation (search for a subpath like qml/QtQuick/Controls/Styles/Desktop) to see what changes w.r.t. Windows and try to adapt the provided solution. This part is left up to the reader.