QComboBox and app.setStyle("cleanlooks")

ghz 昨天 ⋅ 0 views

The code below creates a single QComboBox with QAbstractTableModel model assigned. Strange, if app.setStyle("cleanlooks") is commented out the QCombo does not pull its menu down when it is clicked. Any suggestion why that is happening?

enter image description here

from PyQt import QtGui, QtCore
class tableModel(QtCore.QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QtCore.QAbstractTableModel.__init__(self, parent, *args)
        self.items = [['Item_A000', '10'],['Item_B001', '20'],['Item_A002', '30'],['Item_B003', '40'],['Item_B004', '50']] 

    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.items)  
    def columnCount(self, parent=QtCore.QModelIndex()):
        return 2  

    def data(self, index, role):
        if not index.isValid(): return 
        row=index.row()
        column=index.column()
        return self.items[row][column]

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    # app.setStyle("cleanlooks")

    tModel=tableModel()    

    combobox = QtGui.QComboBox()
    combobox.setModel(tModel)
    combobox.show()       

    sys.exit(app.exec_())

Answer

The issue you are describing is related to the interaction between the QComboBox and the QAbstractTableModel, and how the cleanlooks style affects the behavior of the combo box dropdown. Here are a few key points that might explain why this behavior occurs:

  1. UI Styling and Behavior: The cleanlooks style in PyQt changes the appearance and behavior of UI elements to resemble a more "minimal" or "clean" look. This might affect the interaction between certain widgets, such as how dropdowns or menus behave. When the style is applied, it may be overriding or modifying the default behavior of certain widgets like QComboBox.

  2. Model and View Relationship: QComboBox by default expects a QAbstractItemModel for its model. The code you've written assigns a custom QAbstractTableModel, which is correct, but the style may affect the painting or the interactive behavior of the dropdown menu.

  3. Potential Missing View for ComboBox: When the cleanlooks style is enabled, it might be affecting how the combo box's popup (the dropdown menu) is displayed. It may also disable the default behavior where the menu is pulled down when the combo box is clicked. This behavior could also depend on the QComboBox's interaction with the QAbstractTableModel and whether the model provides enough information for the combo box to trigger the menu properly.

Suggestions to Fix or Investigate:

  1. Force the ComboBox to Use QListView: One way to fix this is to explicitly set a QListView for the QComboBox to use, which can help ensure the correct rendering of the dropdown list. You can set the view for the combo box like this:

    combobox.setView(QtGui.QListView())
    
  2. Set Proper Style for Widgets: Instead of applying a global style (which may interfere with specific widget behaviors), you could try using specific styles or resetting the widget's style.

    combobox.setStyle(QtGui.QStyleFactory.create("Fusion"))
    

    This applies the "Fusion" style which is typically more predictable and standard across platforms.

  3. Debug the Style Effect: You could try experimenting with other styles to narrow down the issue. Try commenting out app.setStyle("cleanlooks") and then experimenting with other styles like Fusion, Windows, or Macintosh (depending on your system) to see if they affect the dropdown behavior.

  4. Override the showPopup Method (Workaround): If you are facing a problem with the popup not showing, you could try manually triggering the popup by overriding the showPopup method. This is more of a workaround, but it can help in specific cases:

    class MyComboBox(QtGui.QComboBox):
        def showPopup(self):
            super().showPopup()
    
    combobox = MyComboBox()
    
  5. Ensure Proper Event Handling: Make sure the event handling for the dropdown is not being overridden or blocked in a way that affects the dropdown. For example, you could check if any event filters or custom event handling code is interfering with the widget's default behavior.

Final Revised Code Example with a ListView:

Here’s an updated version of the code that sets a QListView explicitly for the combo box:

import sys
from PyQt5 import QtGui, QtCore

class tableModel(QtCore.QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QtCore.QAbstractTableModel.__init__(self, parent, *args)
        self.items = [['Item_A000', '10'], ['Item_B001', '20'], ['Item_A002', '30'], ['Item_B003', '40'], ['Item_B004', '50']] 

    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.items)  

    def columnCount(self, parent=QtCore.QModelIndex()):
        return 2  

    def data(self, index, role):
        if not index.isValid(): return 
        row = index.row()
        column = index.column()
        return self.items[row][column]

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    # app.setStyle("cleanlooks")

    tModel = tableModel()    

    combobox = QtGui.QComboBox()
    combobox.setModel(tModel)
    
    # Set explicit view for the combo box
    combobox.setView(QtGui.QListView())

    combobox.show()       

    sys.exit(app.exec_())

This should ensure the QComboBox dropdown behaves correctly, even if the cleanlooks style is applied. Let me know if this helps or if the issue persists!