QCSS precedence versus "in-line code"



  • I am "surprised" at the precedence given to QCSS rules over "in-line" code. Consider the following:

    import sys
    from PyQt5 import QtWidgets, QtGui
    
    
    class Main(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
    
            # set default button minimum height & background color
            ss = 'QPushButton { min-height: 100px; background-color: red; }'
            # comment & uncomment next line
            # QtWidgets.QApplication.instance().setStyleSheet(ss)
    
            self.setWindowTitle("Main")
            self.setGeometry(100, 100, 500, 500)
    
            self.centralWidget = QtWidgets.QWidget(self)
            self.setCentralWidget(self.centralWidget)
            self.centralLayout = QtWidgets.QHBoxLayout(self.centralWidget)
    
            self.btn1 = QtWidgets.QPushButton("Button #1")
            self.centralLayout.addWidget(self.btn1)
    
            self.btn2 = QtWidgets.QPushButton("Button #2")
            
            # set explicit minimum height
            self.btn2.setMinimumHeight(200)
            
            # set explicit button background color
            # (see also my "**" comment at the end of the post)
            pal = QtGui.QPalette()
            pal.setColor(QtGui.QPalette.Button, QtGui.QColor("yellow"))
            self.btn2.setAutoFillBackground(True)
            self.btn2.setPalette(pal)
            
            self.centralLayout.addWidget(self.btn2)
    
            self.show()
    
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
    
        main = Main()
    
        sys.exit(app.exec_())
    

    Compare running this with the QtWidgets.QApplication.instance().setStyleSheet(ss) line commented/uncommented.

    When the style sheet rule is in play, it overrides both the height & color set on btn2 explicitly.

    I come from an HTML/CSS background. There we are used to anything set directly on an element (whether via stylesheet or, say, explicit JavaScript code altering attributes) overriding a CSS rule.

    So, in Qt, I guess I need to regard anything set via a style sheet, at any level, as overriding any corresponding thing the code may have set on the widget explicitly. Is that right?

    Then, to achieve one button different from the default, I have to do it via setStyleSheet() on the widget rather than the explicit "in-line code" making Qt widget calls. Is that right?

    Background: This is problematic for me. I am converting thousands of lines of code over to trying to use a global, external QCSS file, at least for defaults. The behaviour means that I need to find a lot more in the existing code to alter, e.g. I cannot allow any explicit setMinimumHeight() calls to remain, because they get overridden if the QCSS has a defult minimum-height rule. :(

    ** Incidentally: Are you responsible for https://wiki.qt.io/How_to_Change_the_Background_Color_of_QWidget ? Because that is wrong for QPushButton, and other people are attempting to use it as it comes first on search for qt5 widget set color. The code there claims:

    // set black background
    pal.setColor(QPalette::Background, Qt::black);
    

    However, it is not obvious that for a QPushButton you actually need:

    // set black background
    pal.setColor(QPalette::Button, Qt::black);
    

  • Moderators

    Try adding the button to the layout first, then applying your explicit changes. I suppose what happens now is that you set up your custom widget, and then when you add it to layout, the layout is pushing it's stylesheet to that widget.


  • Moderators

    @JonB said in QCSS precedence versus "in-line code":

    So, in Qt, I guess I need to regard anything set via a style sheet, at any level, as overriding any corresponding thing the code may have set on the widget explicitly. Is that right?

    No, that is wrong. QSS works only for the widget you set it on + all children. It does not go up in the parent-child tree.



  • @sierdzio said in QCSS precedence versus "in-line code":

    @JonB said in QCSS precedence versus "in-line code":

    So, in Qt, I guess I need to regard anything set via a style sheet, at any level, as overriding any corresponding thing the code may have set on the widget explicitly. Is that right?

    No, that is wrong. QSS works only for the widget you set it on + all children. It does not go up in the parent-child tree.

    For this one, I think you're misunderstanding me. I know that inheritance is only downward, not upward (remember, I'm familiar with CSS!). I didn't imply otherwise. I meant: no matter where I do set CSS --- e.g. directly on a widget, or on any level of parentage --- that is going to override any explicit, say, setMinimumHeight() calls the code might make directly on the widget, of which there are probably many to track down in the code. And it will apply to any call, not just setMinimumHeight().....



  • @sierdzio said in QCSS precedence versus "in-line code":

    Try adding the button to the layout first, then applying your explicit changes. I suppose what happens now is that you set up your custom widget, and then when you add it to layout, the layout is pushing it's stylesheet to that widget.

    Nope! Done that (moved self.centralLayout.addWidget(self.btn2) up to immediately below self.btn2 = QtWidgets.QPushButton("Button #2")), behaviour is exactly the same, stylesheet overrides "in-line code" ... ?


  • Moderators

    @JonB said in QCSS precedence versus "in-line code":

    Nope! Done that (moved self.centralLayout.addWidget(self.btn2) up to immediately below self.btn2 = QtWidgets.QPushButton("Button #2")), behaviour is exactly the same, stylesheet overrides "in-line code" ... ?

    Looks like a bug to me, then.



  • @sierdzio
    Well, I can't see it's a "bug", as it must be a thorough-going behaviour principle. That's why I illustrated both with a size and a color.

    Is someone able to confirm what the "principle" is here, please?


  • Moderators

    @JonB said in QCSS precedence versus "in-line code":

    Well, I can't see it's a "bug", as it must be a thorough-going behaviour principle.

    If it is not mentioned in the documentation, it is a bug. Besides, the intuition is that when you change something explicitly, it should not be overridden by default global setting, IMO. So it feels buggy to me (esp. since I don't remember it working this way previously).



  • @sierdzio
    I take your point. However it's a pretty fundamental design one way or the other, and I have refactor all code in that light now, I cannot wait till Qt might change its mind in the future. So my immediate problem is to figure out what I might need to look for in my code now which may need changing as a consequence.


  • Lifetime Qt Champion

    Hi,

    From the style sheet documentation. It’s coherent. Style sheets guarantee that what you set is what you get and only what it doesn’t handle, it forwards to the OS style.

    So depending on your needs, you might want to consider implementing your own style like Qt Creator does.



  • @SGaist
    Thank you as ever for your response.

    I have (re-)read the link, and I did not get from it that an explicit, say, QWidget::setMaximumWidth() would be overridden by a generic stylesheet max-width:. But I am not as familiar with Qt as you are.

    So, whether I like it or not, if an application stylesheet has QPushButon { max-width: 100px; }, and that suits 90% of the buttons in the app, but dotted over the code are the occasional btn.setMaximumWidth(XXX)s with different numbers and not suitable for common stylesheet rules, they will have no effect. They would need to be changed to btn.setStyleSheet("max-width: XXXpx;") instead if I want to be sure they come into effect.

    Once stylesheets are in use, you must use setStyleSheet() and not the dedicated Qt properties to be sure to override. Right?


  • Lifetime Qt Champion

    Yes that's right. However, like I wrote before depending on your needs, a custom QStyle might be more suitable.



  • @SGaist
    OK, thanks for confirming.

    What link should I read up for "a custom QStyle" and "you might want to consider implementing your own style like Qt Creator does", as I don't know about this?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.