Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Stylesheet not applied correctly
Forum Updated to NodeBB v4.3 + New Features

Stylesheet not applied correctly

Scheduled Pinned Locked Moved Unsolved Qt for Python
16 Posts 4 Posters 3.3k Views 2 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.
  • G Gazi

    Hello,

    I have found out smth strange about how stylesheet is applied. I have prepared a minimal example, where I have a Drawer widget inside my main window.

    If I have the Drawer as a separate class, the style to it is not applied correctly. Here is a minimal example, where the Drawer should be red, but it is not:

    ################################################################
    import sys
    from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton

    Sample stylesheet

    stylesheet = """
    QWidget#Drawer {
    background-color: red; /* Red background for the drawer */
    }
    """

    class Drawer(QWidget):
    def init(self):
    super().init()
    self.setObjectName('Drawer') # Set the object name for the drawer
    self.setStyleSheet(stylesheet) # Apply the stylesheet to the drawer

        # Create a vertical layout for the drawer
        layout = QVBoxLayout(self)
    
        # Add a button to the drawer
        button = QPushButton("Drawer Button")
        layout.addWidget(button)
    

    class MyWindow(QMainWindow):
    def init(self):
    super().init()
    self.init_ui()

    def init_ui(self):
        self.setWindowTitle("Minimal PySide6 Drawer Example")
    
        # Create a central widget
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
    
        # Create a vertical layout for the central widget
        layout = QVBoxLayout(central_widget)
    
        # Create the drawer widget and add it to the layout
        drawer_widget = Drawer()
        layout.addWidget(drawer_widget)
    

    def main():
    if not QApplication.instance():
    app = QApplication(sys.argv)
    else:
    app = QApplication.instance()

    # Apply the stylesheet
    app.setStyleSheet(stylesheet)
    
    window = MyWindow()
    window.show()
    sys.exit(app.exec())
    

    main()
    #################################################################

    Can anyone explain why the drawer is not set to red?

    Thank you.

    JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by
    #2

    @Gazi
    Please use Code tags (</> icon button) on blocks of code.

    Do either of #Drawer or Drawer work instead of QWidget#Drawer for selector?

    G 1 Reply Last reply
    0
    • JonBJ JonB

      @Gazi
      Please use Code tags (</> icon button) on blocks of code.

      Do either of #Drawer or Drawer work instead of QWidget#Drawer for selector?

      G Offline
      G Offline
      Gazi
      wrote on last edited by
      #3

      @JonB

      Thx for the reply.

      Neither #Drawer, nor Drawer work.

      Here is again the code:

      import sys
      from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton
      
      # Sample stylesheet
      stylesheet = """
          QWidget#Drawer {
              background-color: red;  /* Red background for the drawer */
          }
      """
      
      class Drawer(QWidget):
          def __init__(self):
              super().__init__()
              self.setObjectName('Drawer')  # Set the object name for the drawer
              self.setStyleSheet(stylesheet)  # Apply the stylesheet to the drawer
              
              # Create a vertical layout for the drawer
              layout = QVBoxLayout(self)
      
              # Add a button to the drawer
              button = QPushButton("Drawer Button")
              layout.addWidget(button)
              
      
      class MyWindow(QMainWindow):
          def __init__(self):
              super().__init__()
      
              self.init_ui()
      
          def init_ui(self):
              self.setWindowTitle("Minimal PySide6 Drawer Example")
      
              # Create a central widget
              central_widget = QWidget()
              self.setCentralWidget(central_widget)
      
              # Create a vertical layout for the central widget
              layout = QVBoxLayout(central_widget)
      
              # Create the drawer widget and add it to the layout
              drawer_widget = Drawer()
              layout.addWidget(drawer_widget)
      
      def main():
          if not QApplication.instance():
              app = QApplication(sys.argv)
          else:
              app = QApplication.instance()    
              
          # Apply the stylesheet
          app.setStyleSheet(stylesheet)
          
          window = MyWindow()
          window.show()
          sys.exit(app.exec())
      
      main()
      
      
      SGaistS 1 Reply Last reply
      0
      • G Gazi

        @JonB

        Thx for the reply.

        Neither #Drawer, nor Drawer work.

        Here is again the code:

        import sys
        from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton
        
        # Sample stylesheet
        stylesheet = """
            QWidget#Drawer {
                background-color: red;  /* Red background for the drawer */
            }
        """
        
        class Drawer(QWidget):
            def __init__(self):
                super().__init__()
                self.setObjectName('Drawer')  # Set the object name for the drawer
                self.setStyleSheet(stylesheet)  # Apply the stylesheet to the drawer
                
                # Create a vertical layout for the drawer
                layout = QVBoxLayout(self)
        
                # Add a button to the drawer
                button = QPushButton("Drawer Button")
                layout.addWidget(button)
                
        
        class MyWindow(QMainWindow):
            def __init__(self):
                super().__init__()
        
                self.init_ui()
        
            def init_ui(self):
                self.setWindowTitle("Minimal PySide6 Drawer Example")
        
                # Create a central widget
                central_widget = QWidget()
                self.setCentralWidget(central_widget)
        
                # Create a vertical layout for the central widget
                layout = QVBoxLayout(central_widget)
        
                # Create the drawer widget and add it to the layout
                drawer_widget = Drawer()
                layout.addWidget(drawer_widget)
        
        def main():
            if not QApplication.instance():
                app = QApplication(sys.argv)
            else:
                app = QApplication.instance()    
                
            # Apply the stylesheet
            app.setStyleSheet(stylesheet)
            
            window = MyWindow()
            window.show()
            sys.exit(app.exec())
        
        main()
        
        
        SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #4

        Hi,

        From memory, QWidget#Drawer applies to QWidget objects with an objectName set to Drawer. If you want to apply the stylesheet to widgets from the Drawer class, then just use Drawer.

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

        G 1 Reply Last reply
        1
        • SGaistS SGaist

          Hi,

          From memory, QWidget#Drawer applies to QWidget objects with an objectName set to Drawer. If you want to apply the stylesheet to widgets from the Drawer class, then just use Drawer.

          G Offline
          G Offline
          Gazi
          wrote on last edited by
          #5

          @SGaist

          If you mean to substitute "QWidget#Drawer" with "Drawer" in the stylesheet, then this does not work.

          SGaistS 1 Reply Last reply
          0
          • G Gazi

            @SGaist

            If you mean to substitute "QWidget#Drawer" with "Drawer" in the stylesheet, then this does not work.

            SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #6

            Looks like there's something off when putting your Drawer widget in your MyWindow. If you create and show a Draw instance in your main function, it works correctly.

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

            G 1 Reply Last reply
            0
            • SGaistS SGaist

              Looks like there's something off when putting your Drawer widget in your MyWindow. If you create and show a Draw instance in your main function, it works correctly.

              G Offline
              G Offline
              Gazi
              wrote on last edited by
              #7

              @SGaist

              You are right. When I do not have it as a separate class, but rather create it inside the main window, then it works perfectly. However, this is not the solution, because I have a much more complex app and I cannot have everything inside the main function.

              This is why I made this very minimal example so that the other can reproduce it and maybe someone can figure out what is going on there.

              JonBJ 2 Replies Last reply
              0
              • G Gazi

                @SGaist

                You are right. When I do not have it as a separate class, but rather create it inside the main window, then it works perfectly. However, this is not the solution, because I have a much more complex app and I cannot have everything inside the main function.

                This is why I made this very minimal example so that the other can reproduce it and maybe someone can figure out what is going on there.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #8

                @Gazi
                Just to let you know, I am presently playing with your code! I have Qt 5.15, not Qt 6. behaviour seems to be same (as expected).

                Start by noticing that the following CSS selector does work for your pushbutton:

                stylesheet = """
                    QWidget#Drawer QPushButton {
                        background-color: red;  /* Red background for the drawer */
                    }
                """
                

                Once you specify a selector which names a class/instance (QWidget#Drawer) the rule applies directly to that class/instance (i.e. the Drawer) but does not cascade to its children (QPushButton). This is the root of your issue.

                1 Reply Last reply
                0
                • G Gazi

                  @SGaist

                  You are right. When I do not have it as a separate class, but rather create it inside the main window, then it works perfectly. However, this is not the solution, because I have a much more complex app and I cannot have everything inside the main function.

                  This is why I made this very minimal example so that the other can reproduce it and maybe someone can figure out what is going on there.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #9

                  @Gazi
                  I believe your issue may be because you are trying to inherit widget's color. I refer you to https://doc.qt.io/qtforpython-6/overviews/stylesheet-syntax.html#inheritance

                  In classic CSS, when font and color of an item is not explicitly set, it gets automatically inherited from the parent. By default, when using Qt Style Sheets, a widget does not automatically inherit its font and color setting from its parent widget.

                  Thus for your case I find the following (per the example there) does work:

                  stylesheet = """
                      QWidget#Drawer, QWidget#Drawer * {
                          background-color: red;  /* Red background for the drawer */
                      }
                  """
                  

                  Alternatively you can change to adding the QCoreApplication.setAttribute(Qt.AA_UseStyleSheetPropagationInWidgetStyles, True) statement to your program shown in that topic. (Note: I cannot test PySide6 but that statement may need adjusting I believe for PySide6, they moved all enumerated type values into their own classes, like https://doc.qt.io/qtforpython-6/PySide6/QtCore/Qt.html#PySide6.QtCore.PySide6.QtCore.Qt.ApplicationAttribute. I think you will need something which references Qt.ApplicationAttribute.AA_UseStyleSheetPropagationInWidgetStyles.) This would allow just QWidget#Drawer alone to work as the selector. But it would change the behaviour of all widgets' color inheritance.

                  Otherwise for your type case you just need to add the * all-children-selector to your rules explicitly.

                  The absolute truth? I find Qt's CSS stuff either confusing, inconsistent or hard to get to grips with. I found HTML's CSS easier to work with. I just play with Qt CSS rules till I get what works....

                  SGaistS 1 Reply Last reply
                  2
                  • JonBJ JonB

                    @Gazi
                    I believe your issue may be because you are trying to inherit widget's color. I refer you to https://doc.qt.io/qtforpython-6/overviews/stylesheet-syntax.html#inheritance

                    In classic CSS, when font and color of an item is not explicitly set, it gets automatically inherited from the parent. By default, when using Qt Style Sheets, a widget does not automatically inherit its font and color setting from its parent widget.

                    Thus for your case I find the following (per the example there) does work:

                    stylesheet = """
                        QWidget#Drawer, QWidget#Drawer * {
                            background-color: red;  /* Red background for the drawer */
                        }
                    """
                    

                    Alternatively you can change to adding the QCoreApplication.setAttribute(Qt.AA_UseStyleSheetPropagationInWidgetStyles, True) statement to your program shown in that topic. (Note: I cannot test PySide6 but that statement may need adjusting I believe for PySide6, they moved all enumerated type values into their own classes, like https://doc.qt.io/qtforpython-6/PySide6/QtCore/Qt.html#PySide6.QtCore.PySide6.QtCore.Qt.ApplicationAttribute. I think you will need something which references Qt.ApplicationAttribute.AA_UseStyleSheetPropagationInWidgetStyles.) This would allow just QWidget#Drawer alone to work as the selector. But it would change the behaviour of all widgets' color inheritance.

                    Otherwise for your type case you just need to add the * all-children-selector to your rules explicitly.

                    The absolute truth? I find Qt's CSS stuff either confusing, inconsistent or hard to get to grips with. I found HTML's CSS easier to work with. I just play with Qt CSS rules till I get what works....

                    SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #10

                    @JonB Nice catch ! I forgot about that one.

                    @Gazi out of curiosity, are you using one single stylesheet or one per widget ? If the latter, you could also directly apply the stylesheet without selector to these specific widgets.

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

                    G 1 Reply Last reply
                    0
                    • SGaistS SGaist

                      @JonB Nice catch ! I forgot about that one.

                      @Gazi out of curiosity, are you using one single stylesheet or one per widget ? If the latter, you could also directly apply the stylesheet without selector to these specific widgets.

                      G Offline
                      G Offline
                      Gazi
                      wrote on last edited by
                      #11

                      @SGaist I wanted to have a centralized stylesheet. However, it would be helpful for me if you could point out how to apply it per widget.

                      @JonB Thank you for your response. I tried it out and indeed when I use your code, it will make the drawer button red. However, what surprises me is that the drawer itself still does not get red. So, I added 2 buttons to the drawer to explain better. Only the buttons are red, not the drawer itself, as shown in the pic below:

                      da43e98a-c594-4efc-a5e0-1e479b229ae0-Screenshot from 2023-09-25 11-36-32.png file:///home/gazi/Pictures/Screenshots/Screenshot%20from%202023-09-25%2011-36-32.png

                      Here is the code:

                      import sys
                      from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton
                      
                      # Sample stylesheet
                      stylesheet = """
                          QWidget#Drawer, QWidget#Drawer * {
                              background-color: red;  /* Red background for the drawer */
                          }
                      
                      """
                      
                      class Drawer(QWidget):
                          def __init__(self):
                              super().__init__()
                              self.setObjectName('Drawer')  # Set the object name for the drawer
                              
                              # Create a vertical layout for the drawer
                              layout = QVBoxLayout(self)
                      
                              # Add a button to the drawer
                              button1 = QPushButton("Drawer Button 1")
                              button2 = QPushButton("Drawer Button 2")
                              
                              layout.addWidget(button1)
                              layout.addStretch()
                              layout.addWidget(button2)
                              
                      
                      class MyWindow(QMainWindow):
                          def __init__(self):
                              super().__init__()
                      
                              self.init_ui()
                      
                          def init_ui(self):
                              self.setWindowTitle("Minimal PySide6 Drawer Example")
                      
                              # Create a central widget
                              central_widget = QWidget()
                              self.setCentralWidget(central_widget)
                      
                              # Create a vertical layout for the central widget
                              layout = QVBoxLayout(central_widget)
                      
                              # Create the drawer widget and add it to the layout
                              drawer_widget = Drawer()
                              layout.addWidget(drawer_widget)
                      
                      def main():
                          if not QApplication.instance():
                              app = QApplication(sys.argv)
                          else:
                              app = QApplication.instance()    
                              
                          # Apply the stylesheet
                          app.setStyleSheet(stylesheet)
                          
                          window = MyWindow()
                          window.show()
                          sys.exit(app.exec())
                      
                      main()
                      
                      

                      Shouldn't the entire Drawer widget be red?

                      Thanks a lot for the support.

                      JonBJ 1 Reply Last reply
                      0
                      • G Gazi

                        @SGaist I wanted to have a centralized stylesheet. However, it would be helpful for me if you could point out how to apply it per widget.

                        @JonB Thank you for your response. I tried it out and indeed when I use your code, it will make the drawer button red. However, what surprises me is that the drawer itself still does not get red. So, I added 2 buttons to the drawer to explain better. Only the buttons are red, not the drawer itself, as shown in the pic below:

                        da43e98a-c594-4efc-a5e0-1e479b229ae0-Screenshot from 2023-09-25 11-36-32.png file:///home/gazi/Pictures/Screenshots/Screenshot%20from%202023-09-25%2011-36-32.png

                        Here is the code:

                        import sys
                        from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton
                        
                        # Sample stylesheet
                        stylesheet = """
                            QWidget#Drawer, QWidget#Drawer * {
                                background-color: red;  /* Red background for the drawer */
                            }
                        
                        """
                        
                        class Drawer(QWidget):
                            def __init__(self):
                                super().__init__()
                                self.setObjectName('Drawer')  # Set the object name for the drawer
                                
                                # Create a vertical layout for the drawer
                                layout = QVBoxLayout(self)
                        
                                # Add a button to the drawer
                                button1 = QPushButton("Drawer Button 1")
                                button2 = QPushButton("Drawer Button 2")
                                
                                layout.addWidget(button1)
                                layout.addStretch()
                                layout.addWidget(button2)
                                
                        
                        class MyWindow(QMainWindow):
                            def __init__(self):
                                super().__init__()
                        
                                self.init_ui()
                        
                            def init_ui(self):
                                self.setWindowTitle("Minimal PySide6 Drawer Example")
                        
                                # Create a central widget
                                central_widget = QWidget()
                                self.setCentralWidget(central_widget)
                        
                                # Create a vertical layout for the central widget
                                layout = QVBoxLayout(central_widget)
                        
                                # Create the drawer widget and add it to the layout
                                drawer_widget = Drawer()
                                layout.addWidget(drawer_widget)
                        
                        def main():
                            if not QApplication.instance():
                                app = QApplication(sys.argv)
                            else:
                                app = QApplication.instance()    
                                
                            # Apply the stylesheet
                            app.setStyleSheet(stylesheet)
                            
                            window = MyWindow()
                            window.show()
                            sys.exit(app.exec())
                        
                        main()
                        
                        

                        Shouldn't the entire Drawer widget be red?

                        Thanks a lot for the support.

                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by JonB
                        #12

                        @Gazi
                        The drawer QWidget itself is not red because of https://doc.qt.io/qtforpython-6/overviews/stylesheet-reference.html#list-of-stylable-widgets, QWidget item:

                        Supports only the background , background-clip and background-origin properties.
                        If you subclass from QWidget , you need to provide a paintEvent for your custom QWidget as below:

                        If you want that, in your Drawer class you need (tested under my PySide2/Qt5):

                        from PySide2.QtWidgets import ..., QStyle, QStyleOption
                        from PySide2.QtGui import QPainter
                        
                        class Drawer(QWidget):
                            def paintEvent(self, arg__0):
                                opt = QStyleOption()
                                opt.initFrom(self)
                                p = QPainter(self)
                                self.style().drawPrimitive(QStyle.PE_Widget, opt, p, self)
                        
                        G 1 Reply Last reply
                        3
                        • JonBJ JonB

                          @Gazi
                          The drawer QWidget itself is not red because of https://doc.qt.io/qtforpython-6/overviews/stylesheet-reference.html#list-of-stylable-widgets, QWidget item:

                          Supports only the background , background-clip and background-origin properties.
                          If you subclass from QWidget , you need to provide a paintEvent for your custom QWidget as below:

                          If you want that, in your Drawer class you need (tested under my PySide2/Qt5):

                          from PySide2.QtWidgets import ..., QStyle, QStyleOption
                          from PySide2.QtGui import QPainter
                          
                          class Drawer(QWidget):
                              def paintEvent(self, arg__0):
                                  opt = QStyleOption()
                                  opt.initFrom(self)
                                  p = QPainter(self)
                                  self.style().drawPrimitive(QStyle.PE_Widget, opt, p, self)
                          
                          G Offline
                          G Offline
                          Gazi
                          wrote on last edited by
                          #13

                          @JonB Thx for pointing it out. Still i have a lot of trouble to understand why they made it so complicated. I don't know if there are many people who find it complicated, but i guess it would be much more convenient to have some styling capabilities as one has in react-native.

                          1 Reply Last reply
                          0
                          • G Offline
                            G Offline
                            Gazi
                            wrote on last edited by
                            #14

                            @JonB And one more thing, is there a way to specify that i do not want my child widgets to take the style of the parent? That would solve quite some things.

                            SGaistS 1 Reply Last reply
                            0
                            • G Gazi

                              @JonB And one more thing, is there a way to specify that i do not want my child widgets to take the style of the parent? That would solve quite some things.

                              SGaistS Offline
                              SGaistS Offline
                              SGaist
                              Lifetime Qt Champion
                              wrote on last edited by
                              #15

                              @Gazi depending on the result you are after, this article from KDAB about QStyle VS stylesheet might be of interest.

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

                              1 Reply Last reply
                              0
                              • J Offline
                                J Offline
                                jcyrss
                                wrote on last edited by
                                #16

                                QSS has too much exceptional rules, which makes it hard to use. Hope it could be simplified.

                                1 Reply Last reply
                                0

                                • Login

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