StyleSheets: How to apply individual primitive styles



  • Hi, in my quest to switch from raw painting to style-aware widgets I am a little stuck when it comes to styling individual primitives/controls within a paint event.

    I find rect, features can be updated ok, but colors cannot be set and are overridden by the stylesheet.
    I have made an example here (In python while testing but I also do c++)

    class MyWidget(QtWidgets.QWidget):
        textChanged = QtCore.Signal(str)
    
        def __init__(self, parent=None):
            super(MyWidget, self).__init__(parent)
            self._pressed = False
            self._text = ""
        
        def _setText(self, text):
            if text == self._text:
                return
            self._text = str(text)
            self.textChanged.emit(self._text)
        
        def _text(self):
            return self._text
        
        text = QtCore.Property(str, _text, _setText, notify=textChanged)
        
        def paintEvent(self, event):
            painter = QtWidgets.QStylePainter(self)
            # frame
            rect_option = QtWidgets.QStyleOptionFrame()
            rect_option.initFrom(self)
            rect_option.frameShape = QtWidgets.QFrame.StyledPanel
            rect_option.features = QtWidgets.QStyleOptionFrame.Rounded
            rect_option.lineWidth = 5
            rect_option.midLineWidth = 5
            rect_option.palette.setBrush(QtGui.QPalette.Background, QtGui.QColor("#FF0000"))
            painter.drawPrimitive(QtWidgets.QStyle.PE_Frame, rect_option)
            
            # Button
            btn_options = QtWidgets.QStyleOptionButton()
            btn_options.initFrom(self)
            btn_options.rect = self.rect()
            btn_options.rect.adjust(10, 10, -10, -10)
            btn_options.features = QtWidgets.QStyleOptionButton.DefaultButton
            btn_options.text = self._text
            btn_options.palette.setBrush(QtGui.QPalette.Button, QtGui.QColor("#FF0000"))
            if self._pressed:
                btn_options.state |= QtWidgets.QStyle.State_Sunken
            else:
                btn_options.state |= QtWidgets.QStyle.State_Raised
            painter.drawControl(QtWidgets.QStyle.CE_PushButton, btn_options)
        
        def mousePressEvent(self, event):
            self._pressed = True
            self.repaint()
            event.accept()
        
        def mouseReleaseEvent(self, event):
            self._pressed = False
            self.repaint()
            event.accept()
            
    widget = QtWidgets.QWidget()
    layout = QtWidgets.QVBoxLayout(widget)
    my_widget = MyWidget()
    layout.addWidget(my_widget)
    
    widget.setStyleSheet("""
    MyWidget{
        qproperty-text: test;
        background: rgba(46, 204, 113, 0.8);
        min-width: 100px;
        min-height: 50px;
    }
    """)
    
    widget.show()
    

    The rect_options (frame) lineWidth, color and btn_options (button) are not applied.
    What is the correct method of building up primitives for drawing where I want them to have different colors, widths?



  • @Mr-MinimalEffort said in StyleSheets: How to apply individual primitive styles:

    but colors cannot be set and are overridden by the stylesheet.

    Until someone more knowledgeable answers, my understanding is this is intended behaviour: stylesheet rules override style/painting.



  • Yep I get that, and the source does reflect that as looking deeper in the source does show that the QStyleSheetStyle is run after my own QStyle.

    In that case, What is the standard process for painting widgets in a style-aware fashion? Do I need to forgo the palette and take colors from custom properties instead?

    Are there any examples of more complex paintEvents relying solely on QStylePainter (Drawing primitive, complex and control instead of rect, line, etc)


Log in to reply