Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QCSS precedence versus "in-line code"
Forum Updated to NodeBB v4.3 + New Features

QCSS precedence versus "in-line code"

Scheduled Pinned Locked Moved Unsolved General and Desktop
13 Posts 3 Posters 3.3k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    JonB
    wrote on 4 Jan 2018, 11:14 last edited by
    #1

    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);
    
    S 1 Reply Last reply 4 Jan 2018, 11:35
    0
    • S Offline
      S Offline
      sierdzio
      Moderators
      wrote on 4 Jan 2018, 11:35 last edited by
      #2

      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.

      (Z(:^

      J 1 Reply Last reply 4 Jan 2018, 11:40
      0
      • J JonB
        4 Jan 2018, 11:14

        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);
        
        S Offline
        S Offline
        sierdzio
        Moderators
        wrote on 4 Jan 2018, 11:35 last edited by
        #3

        @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.

        (Z(:^

        J 1 Reply Last reply 4 Jan 2018, 11:38
        0
        • S sierdzio
          4 Jan 2018, 11:35

          @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.

          J Offline
          J Offline
          JonB
          wrote on 4 Jan 2018, 11:38 last edited by JonB 1 Apr 2018, 11:39
          #4

          @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().....

          1 Reply Last reply
          0
          • S sierdzio
            4 Jan 2018, 11:35

            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.

            J Offline
            J Offline
            JonB
            wrote on 4 Jan 2018, 11:40 last edited by JonB 1 Apr 2018, 11:42
            #5

            @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" ... ?

            S 1 Reply Last reply 4 Jan 2018, 11:48
            0
            • J JonB
              4 Jan 2018, 11:40

              @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" ... ?

              S Offline
              S Offline
              sierdzio
              Moderators
              wrote on 4 Jan 2018, 11:48 last edited by
              #6

              @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.

              (Z(:^

              J 1 Reply Last reply 4 Jan 2018, 11:57
              0
              • S sierdzio
                4 Jan 2018, 11:48

                @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.

                J Offline
                J Offline
                JonB
                wrote on 4 Jan 2018, 11:57 last edited by
                #7

                @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?

                S 1 Reply Last reply 4 Jan 2018, 12:56
                0
                • J JonB
                  4 Jan 2018, 11:57

                  @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?

                  S Offline
                  S Offline
                  sierdzio
                  Moderators
                  wrote on 4 Jan 2018, 12:56 last edited by
                  #8

                  @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).

                  (Z(:^

                  J 1 Reply Last reply 4 Jan 2018, 17:33
                  0
                  • S sierdzio
                    4 Jan 2018, 12:56

                    @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).

                    J Offline
                    J Offline
                    JonB
                    wrote on 4 Jan 2018, 17:33 last edited by JonB 1 Apr 2018, 17:34
                    #9

                    @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.

                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on 4 Jan 2018, 19:16 last edited by
                      #10

                      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.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      J 1 Reply Last reply 4 Jan 2018, 20:31
                      1
                      • SGaistS SGaist
                        4 Jan 2018, 19:16

                        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.

                        J Offline
                        J Offline
                        JonB
                        wrote on 4 Jan 2018, 20:31 last edited by JonB 1 Apr 2018, 20:33
                        #11

                        @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?

                        1 Reply Last reply
                        1
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on 5 Jan 2018, 18:39 last edited by
                          #12

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

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          J 1 Reply Last reply 5 Jan 2018, 19:20
                          0
                          • SGaistS SGaist
                            5 Jan 2018, 18:39

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

                            J Offline
                            J Offline
                            JonB
                            wrote on 5 Jan 2018, 19:20 last edited by JonB 1 May 2018, 19:20
                            #13

                            @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?

                            1 Reply Last reply
                            0

                            1/13

                            4 Jan 2018, 11:14

                            • Login

                            • Login or register to search.
                            1 out of 13
                            • First post
                              1/13
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • Users
                            • Groups
                            • Search
                            • Get Qt Extensions
                            • Unsolved