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. Custom QWidget setStyleSheet not working - Python
QtWS25 Last Chance

Custom QWidget setStyleSheet not working - Python

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 3 Posters 2.5k Views
  • 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.
  • O Offline
    O Offline
    orensbruli
    wrote on last edited by aha_1980
    #1

    Hello,

    I'm trying to set the background color of a custom QWidget. I have tried with this minimum example:

    class other(QWidget):
    	def __init__(self, parent = None):
    		super(other, self).__init__(parent)
    		# self.setAutoFillBackground(False)
    
    
    
    if __name__ == '__main__':
    	app = QApplication(sys.argv)
    	main_widget = QWidget()
    	main_layout = QVBoxLayout()
    	main_widget.setLayout(main_layout)
    
    	main_widget.setStyleSheet(".QWidget{background-color: blue}")
    
    	child_widget1 = QWidget()
    	child_widget1.setStyleSheet(".QWidget{background-color: green}")
    
    	child_widget2 = QWidget()
    	child_widget2.setStyleSheet(".QWidget{background-color: white}")
    
    	other = other()
    	other.setStyleSheet(".other{background-color: black}")
    
    	main_widget.setMinimumSize(QSize(600, 600))
    	main_layout.addWidget(child_widget1)
    	main_layout.addWidget(child_widget2)
    	main_layout.addWidget(other)
    
    	main_widget.show()
    	sys.exit(app.exec_())
    

    I can change the first two widget colors without problem. But the last one, which my own class just inheriting from QWidget doesn't change its color to black.

    If I just change my "other" class to inherit from QLabel everything work as expected. Can someone bring some light into this behavior?

    Working example with QLabel:

    class other(QLabel):
    	def __init__(self, parent = None):
    		super(other, self).__init__(parent)
    		# self.setAutoFillBackground(False)
    
    
    
    if __name__ == '__main__':
    	app = QApplication(sys.argv)
    	main_widget = QWidget()
    	main_layout = QVBoxLayout()
    	main_widget.setLayout(main_layout)
    
    	main_widget.setStyleSheet(".QWidget{background-color: blue}")
    
    	child_widget1 = QWidget()
    	child_widget1.setStyleSheet(".QWidget{background-color: green}")
    
    	child_widget2 = QWidget()
    	child_widget2.setStyleSheet(".QWidget{background-color: white}")
    
    	other = other()
    	other.setStyleSheet(".other{background-color: black}")
    
    	main_widget.setMinimumSize(QSize(600, 600))
    	main_layout.addWidget(child_widget1)
    	main_layout.addWidget(child_widget2)
    	main_layout.addWidget(other)
    
    	main_widget.show()
    	sys.exit(app.exec_())
    
    JonBJ 1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by mrjj
      #2

      Hi
      For a plain QWidget subclass, you must do

       void CustomWidget::paintEvent(QPaintEvent *)
       {
           QStyleOption opt;
           opt.init(this);
           QPainter p(this);
           style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
       }
      
      def paintEvent(self, pe):
          o = QStyleOption()
          o.initFrom(self)
          p = QPainter(self)
          self.style().drawPrimitive(QStyle.PE_Widget, o, p, self)
      

      to let it paint with style sheet effect. ( assuming you did overwrite paintEvent for your class)

      1 Reply Last reply
      3
      • O orensbruli

        Hello,

        I'm trying to set the background color of a custom QWidget. I have tried with this minimum example:

        class other(QWidget):
        	def __init__(self, parent = None):
        		super(other, self).__init__(parent)
        		# self.setAutoFillBackground(False)
        
        
        
        if __name__ == '__main__':
        	app = QApplication(sys.argv)
        	main_widget = QWidget()
        	main_layout = QVBoxLayout()
        	main_widget.setLayout(main_layout)
        
        	main_widget.setStyleSheet(".QWidget{background-color: blue}")
        
        	child_widget1 = QWidget()
        	child_widget1.setStyleSheet(".QWidget{background-color: green}")
        
        	child_widget2 = QWidget()
        	child_widget2.setStyleSheet(".QWidget{background-color: white}")
        
        	other = other()
        	other.setStyleSheet(".other{background-color: black}")
        
        	main_widget.setMinimumSize(QSize(600, 600))
        	main_layout.addWidget(child_widget1)
        	main_layout.addWidget(child_widget2)
        	main_layout.addWidget(other)
        
        	main_widget.show()
        	sys.exit(app.exec_())
        

        I can change the first two widget colors without problem. But the last one, which my own class just inheriting from QWidget doesn't change its color to black.

        If I just change my "other" class to inherit from QLabel everything work as expected. Can someone bring some light into this behavior?

        Working example with QLabel:

        class other(QLabel):
        	def __init__(self, parent = None):
        		super(other, self).__init__(parent)
        		# self.setAutoFillBackground(False)
        
        
        
        if __name__ == '__main__':
        	app = QApplication(sys.argv)
        	main_widget = QWidget()
        	main_layout = QVBoxLayout()
        	main_widget.setLayout(main_layout)
        
        	main_widget.setStyleSheet(".QWidget{background-color: blue}")
        
        	child_widget1 = QWidget()
        	child_widget1.setStyleSheet(".QWidget{background-color: green}")
        
        	child_widget2 = QWidget()
        	child_widget2.setStyleSheet(".QWidget{background-color: white}")
        
        	other = other()
        	other.setStyleSheet(".other{background-color: black}")
        
        	main_widget.setMinimumSize(QSize(600, 600))
        	main_layout.addWidget(child_widget1)
        	main_layout.addWidget(child_widget2)
        	main_layout.addWidget(other)
        
        	main_widget.show()
        	sys.exit(app.exec_())
        
        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #3

        @orensbruli
        @mrjj is quite correct!

        https://stackoverflow.com/a/32889486 even gives you Python code for this :)

        And if, like me, you wonder why it's needed given that QWidget itself does work and you're deriving from it, there's a comment on that page including [my italics]:

        I can only guess that by default Qt's style mechanism that draws the control (QStyle::drawControl) performs some default painting for QWidgets (as identified by meta data as result of Q_OBJECT in QWidget). As soon as you provide Q_OBJECT for your own widget derivative, the default behaviour does not hold anymore, and Qt's drawControl begins to rely on code within paintEvent to draw the control.

        O 1 Reply Last reply
        3
        • JonBJ JonB

          @orensbruli
          @mrjj is quite correct!

          https://stackoverflow.com/a/32889486 even gives you Python code for this :)

          And if, like me, you wonder why it's needed given that QWidget itself does work and you're deriving from it, there's a comment on that page including [my italics]:

          I can only guess that by default Qt's style mechanism that draws the control (QStyle::drawControl) performs some default painting for QWidgets (as identified by meta data as result of Q_OBJECT in QWidget). As soon as you provide Q_OBJECT for your own widget derivative, the default behaviour does not hold anymore, and Qt's drawControl begins to rely on code within paintEvent to draw the control.

          O Offline
          O Offline
          orensbruli
          wrote on last edited by
          #4

          @JonB said in Custom QWidget setStyleSheet not working - Python:

          d Qt's drawControl begins to rely on code within paintEvent to draw the control.

          Thank you both @mrjj and @JonB! It works and @JonB as you guessed I was wondering why it's like that and after the explanation it still makes me fell like it's a really weird behavior. If it happens with QWidget, I think anyone would also expect it to happen with any other derived widget as QLabel or QButton, but with those widgets it works as the intuition says it should work.

          mrjjM 1 Reply Last reply
          0
          • O orensbruli

            @JonB said in Custom QWidget setStyleSheet not working - Python:

            d Qt's drawControl begins to rely on code within paintEvent to draw the control.

            Thank you both @mrjj and @JonB! It works and @JonB as you guessed I was wondering why it's like that and after the explanation it still makes me fell like it's a really weird behavior. If it happens with QWidget, I think anyone would also expect it to happen with any other derived widget as QLabel or QButton, but with those widgets it works as the intuition says it should work.

            mrjjM Offline
            mrjjM Offline
            mrjj
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @orensbruli
            Hi
            well default paintEvent for QWidget does nothing.
            https://code.woboq.org/qt5/qtbase/src/widgets/kernel/qwidget.cpp.html
            line 9810
            But the others already uses QStyle to paint.
            so jonBs guessing seems pretty straight on.

            1 Reply Last reply
            1
            • O Offline
              O Offline
              orensbruli
              wrote on last edited by
              #6

              @orensbruli said in Custom QWidget setStyleSheet not working - Python:

              nyone would also expect it to happen with any other derived widget as

              @mrjj Thank you. What I then don't understand is why the setStyleSheet to child_widget1 on my example works. It's a QWidget, so no paintEvent is implemented on this either, right? Why does it works in this case? Thank you again for your patience.

              JonBJ 1 Reply Last reply
              0
              • O orensbruli

                @orensbruli said in Custom QWidget setStyleSheet not working - Python:

                nyone would also expect it to happen with any other derived widget as

                @mrjj Thank you. What I then don't understand is why the setStyleSheet to child_widget1 on my example works. It's a QWidget, so no paintEvent is implemented on this either, right? Why does it works in this case? Thank you again for your patience.

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

                @orensbruli
                Please re-read the link/comment I posted, and the bit I said I had italicized. That explains/guesses why QWidegt (seems to) work directly, but anything directly sub-classed from QWidget does not:

                (QStyle::drawControl) performs some default painting for QWidgets (as identified by meta data as result of Q_OBJECT in QWidget).

                This is saying that there is (presumably) some code in Qt base which has a special case for drawing QWidget if and only if that is widget's exact type. It goes on to say that if you derive directly from QWidget you lose that route of code and hence have to re-provide your own. OTOH if you derive from any Qt class derived from QWidget, e.g. QLabel, that already has the necessary explicit paint code so you do not need to add same yourself in such a case.

                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