pythonuser-interfacepyqt5qcombobox

QComboBox list popup display in Fusion style


I am using PyQt5. I want to know how to make my QComboBox open with ±10 items instead of the full screen. This only happens with the fusion style applied. Is there any way I can make this behave with a small drop down instead? I have tried to use setMaxVisibleItems(5), but it didn't make a difference.

Here is what it is looking like now:

example


Solution

  • As pointed out in QTBUG-89037, there's an undocumented stylesheet property that can be used to change the behaviour of the popup:

    setStyleSheet('QComboBox {combobox-popup: 0}')
    

    A value of 0 will show the normal scrollable list-view with a maximum number of visible items, whilst a value of 1 shows the humungous menu.

    However, in some circumstances, setting a stylesheet may have undesirable side-effects, since it could potentially interfere with the default behaviour of QStyle. So an alternative solution might be to use a proxy-style, and reimplement its styleHint method so that it returns either 0 or 1 for QStyle.SH_ComboBox_Popup.

    Both of these solutions work with both Qt5 and Qt6, and will also work for styles such as "cleanlooks" as well as "fusion".

    Here's a simple demo that implements both solutions:

    screenshot

    from PyQt5 import QtWidgets
    # from PyQt6 import QtWidgets
    
    class Window(QtWidgets.QWidget):
        def __init__(self):
            super().__init__()
            self.combo = QtWidgets.QComboBox()
            self.combo.addItems(f'Item-{i:02}' for i in range(1, 50))
            layout = QtWidgets.QVBoxLayout(self)
            layout.addWidget(self.combo)
    
    class ProxyStyle(QtWidgets.QProxyStyle):
        def styleHint(self, hint, option, widget, data):
            if hint == QtWidgets.QStyle.StyleHint.SH_ComboBox_Popup:
                return 0
            return super().styleHint(hint, option, widget, data)
    
    if __name__ == '__main__':
    
        app = QtWidgets.QApplication(['Combo Test'])
    
        app.setStyle('fusion')
    #     app.setStyle('cleanlooks')
    #     style = ProxyStyle(app.style())
    #     app.setStyle(style)
    
        app.setStyleSheet('QComboBox {combobox-popup: 0}')
    
        window = Window()
        window.setGeometry(600, 100, 200, 75)
        window.show()
        app.exec()