0

I've got a pretty large PyQt5 application that I'm finally polishing with some colors. I've created a QPalette() and pass that to the app at launch. For the most part, it works (yay!). But not all of the child widgets are picking up the QPalette settings, and so I added a StyleSheet, but that again isn't working consistently. The only way I've been able to impact a widget color is by directly adding it when the widget is created, which is fine in something small.

The Main window:

    class MyBigApplication(QMainWindow, QWidget):
            def __init__(self):
                super(MyBigApplication, self).__init__()
        
            # ... load the various pieces, which include prompting user login and making some background connections.
        
            # Build the GUI
            def init_ui(self):
        
                self.statusBar().showMessage('Welcome to MyBigApplication!')
        
                self.grid_layout = QGridLayout()
        
                # Initialize tab screen
                self.tabs = QTabWidget()
                self.tabs.setTabShape(QTabWidget.Triangular)
                self.foo = fooTab(self, self.tabs)
                self.bar = barTab(self, self.tabs)
                self.baz = bazTab(self, self.tabs)
        
                self.grid_layout.addWidget(self.tabs,0,1,4,1)
                
                main_widget = QWidget()
                main_widget.setLayout(self.grid_layout)
                self.setCentralWidget(main_widget)
        
                # Additional setup of menus and such
        
        if __name__.endswith('__main__'):
            app = QCoreApplication.instance()
            while app is not None:
                app.close()
            app = QApplication(sys.argv)
        
            app.setStyle('Fusion')
        
            dark_palette = QPalette()
        
            # Define some colors to get started
            light_grey = QColor(243,243,243)
            medium_grey = QColor(211,216,219)
            dark_grey = QColor(52,59,64)
        
            dark_palette.setColor(QPalette.Window, QColor(dark_grey)) 
            dark_palette.setColor(QPalette.AlternateBase, QColor(medium_grey))
            dark_palette.setColor(QPalette.Button, QColor(dark_grey))
            dark_palette.setColor(QPalette.Base, QColor(25, 25, 25)) # almost black
            dark_palette.setColor(QPalette.Link, QColor(green)) 
            dark_palette.setColor(QPalette.Highlight, QColor(half_green))
            dark_palette.setColor(QPalette.WindowText, QColor(light_grey))
            dark_palette.setColor(QPalette.ToolTipBase, QColor(light_grey))
            dark_palette.setColor(QPalette.ToolTipText, QColor(light_grey))
            dark_palette.setColor(QPalette.Text, QColor(light_grey))
            dark_palette.setColor(QPalette.ButtonText, QColor(light_grey))
            dark_palette.setColor(QPalette.BrightText, Qt.red)
            dark_palette.setColor(QPalette.HighlightedText, Qt.black)
        
            app.setPalette(dark_palette)
            
            app.setFont(QFont('Franklin Gothic Book', 9))
        
            app.setStyleSheet("""
                QMainWindow {
        
                }
                QToolTip { 
                    color: #f3f3f3; 
                    background-color: #2a82da; 
                    border: 1px solid white; 
                }
                QTableView {   # This works
                    border: 1px solid #218a21 
                }
                QPushButton {   # And this works
                    padding: 10px 15px 10px 15px,
                }
                QPushButton:hover {   # But this does not
                    background-color: red,
                }
                QTableView::item:alternate {  # And this also does not
                    background-color: #d3d8db,
                }
                """)
        
            execute = MyBigApplication()
            sys.exit(app.exec_())

The fooTab includes tables of data:

class fooTab(QWidget):
    def __init__(self, parent, tabs):
        super(fooTab,self).__init__()
        self.root = parent
        self.tabs = tabs

    def init_foo_one(self):
        self.foo_tab = QWidget()
        self.tabs.addTab(self.foo_tab, 'FOO')
        tab_layout = QVBoxLayout()
        foo_id_box = QGroupBox('FOO DATA')

        clear_button = QPushButton('Clear Foo Data Table')
        clear_button.clicked.connect(self.clear_foo_table)
        
        # Set up the Table Model/View/Proxy
        self.foo_id_table = QTableView()

        self.foo_data_model = fooTableModel()  # This is a QAbstractTableModel class
        
        self.foo_data_model.setDataDict(data)
        self.foo_id_table_columns = ['1','2','3','4']
        self.foo_resizable_cols = [0,1,2,3,4]
        self.foo_data_model.setDataHeader(self.foo_id_table_columns)
        self.foo_table_proxy.setSourceModel(self.foo_data_model)
        self.foo_id_table.setModel(self.foo_table_proxy)
        self.foo_id_table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.foo_id_table.setSortingEnabled(True)
        self.foo_id_table.setWordWrap(False)
        self.foo_id_table.setAlternatingRowColors(True)

        
        # Create a layout for that box using a grid
        foo_id_box_layout = QGridLayout()

        # Add the widgets into the layout
        foo_id_box_layout.addWidget(self.foo_id_table,0,0,1,5)
        foo_id_box_layout.addWidget(clear_button,1,2,1,1)
        
        # Setup the layout to be displayed in the box
        foo_id_box.setLayout(foo_id_box_layout)
        tab_layout.addWidget(foo_id_box)
        self.foo_tab.setLayout(tab_layout)

The bazTab:

    class BazTab(QWidget):
        def __init__(self, parent, tabs):
            super(BazTab,self).__init__()
            self.root = parent
            self.tabs = tabs
            self.h1_font = QFont()
            self.h1_font.setBold(True)
            self.h1_font.setPointSize(16)
            self.h2_font = QFont()
            self.h2_font.setBold(False)
            self.h2_font.setPointSize(12)
            self.h3_font = QFont()
            self.h3_font.setBold(True)
            self.init_ui()
    
    
        def init_ui(self):
            self.component_tab = QScrollArea()
            self.tabs.addTab(self.baz_tab, 'Baz')
            self.tab_layout = QHBoxLayout()
            self.component_tab.setLayout(self.tab_layout)
            
            component_button_box = QGroupBox('Various Buttons')
            component_button_layout = QVBoxLayout()
            component_button_layout.setAlignment(Qt.AlignTop)
            component_button_box.setLayout(component_button_layout)
            self.tab_layout.addWidget(component_button_box)
    
            first_button = QPushButton('Request #1')
            first_button.clicked.connect(self.request_one)
            component_button_layout.addWidget(first_button)
            
            second_button = QPushButton('Request #2')
            second_button.clicked.connect(self.request_two)
            component_button_layout.addWidget(second_button)
            
            # Several more buttons created in here
            # None of these buttons look like the buttons in the info dialog (which have a color from the QPalette)

I can manually edit the QTableView to show alternating colors, only if I add it to each instance.
I cannot get some of the QPushButtons to change, even when I add each instance's styleSheet.

Using the QPalette has saved a ton, by not having to modify widget by widget. For the extra details, I'm fine to use the app.setStyleSheet except that it doesn't always work.

Is it me, or is this just the way it is?

A_Wunder
  • 96
  • 1
  • 7
  • As the documentation of [`setPalette()`](https://doc.qt.io/qt-5/qapplication.html#setPalette) clearly notes: "**Warning:** Do not use this function in conjunction with Qt Style Sheets. When using style sheets, the palette of a widget can be customized using the "color", "background-color", "selection-color", "selection-background-color" and "alternate-background-color"." – musicamante Jan 11 '23 at 20:22
  • 1
    Also: the stylesheet has multiple typos (the commas instead of semicolon), and you should use the [`alternate-background-color`](https://doc.qt.io/qt-5/stylesheet-reference.html#alternate-background-color-prop). – musicamante Jan 11 '23 at 20:39
  • @musicamante Oh, those stupid, stupid semicolons! Putting those into place in the StyleSheet portion of the main application made everything work, and I was able to take off the component-specific stylesheet edits. Regarding the warning to not combine `setPalette()` with `setStyleSheet()` - I guess the solution is to ditch the palette altogether? There's things I need to be able to do, like improving the hover action on a button, that I don't see available in palette, or that have unintended side-effects because the palette control touches more components than I want to modify. – A_Wunder Jan 11 '23 at 22:44
  • You have to consider that the palette is a *hint*, the Qt style (without style sheets) decides how to use those colors or even ignore them, for instance some styles use the `Button` role as color for certain elements of some widgets, while others use the `Window` role, and some even *blend* different color roles; the QStyle also decides if and how to use the palette for states (like `:hover`). Also remember that, when using style sheets, some color properties alter the widget palette (see [this related answer](//stackoverflow.com/a/71231822)). – musicamante Jan 11 '23 at 23:21
  • Note that the quote in my first comment can be misleading. In reality, you *can* use `setPalette()` and stylesheets, as long as you do it with awareness: remember that style sheet color values can also use a [palette role](//doc.qt.io/qt-5/stylesheet-reference.html#paletterole), meaning that you can set the **application** palette with custom colors, and set color values in the stylesheet corresponding to any role you need. Note that this will **not** work with `widget.setPalette()`, as the style sheet of the widget can only access the palette of the application. – musicamante Jan 12 '23 at 00:40

0 Answers0