Search code examples
pythonqtpyside2

Custom widget background color in pyside2


Trying to work out how to set the background color in a QWidget. Here is my code:

class ParentTester(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        left = ColorTester(self)
        right = QFrame(self)
        right.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        layout = QHBoxLayout()
        layout.addWidget(left)
        layout.addWidget(right)
        self.setLayout(layout)


class ColorTester(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        palette = self.palette()
        palette.setColor(QPalette.Window, QColor(128, 0, 0))
        self.setPalette(palette)

def main():
    import sys
    from PySide2.QtWidgets import QApplication

    app = QApplication([])

    works = True

    if works:
        win = ColorTester()
    else:
        win = ParentTester()
    win.show()
    win.resize(640, 480)

    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

This works if I create the class as a topmost window. However if I make it a child of another control, the background color goes back to the default. Some of the other color roles do take effect, but not the background color. Not only that, but the colors get passed through to child controls.

How can I change the background color of a control but not its child controls?


Solution

  • I finally settled on overriding paintEvent for my widget. Setting the color in the palette always seems to pass the color down to child controls, which is not what I wanted. Here is an example of what worked for me. This is a QFrame that takes the default background color and darkens and green-shifts it slightly.

    class GreenFrame(QFrame):
        def __init__(self, parent=None):
            super().__init__(parent)
            r, g, b, a = self.palette().color(QPalette.Window).toTuple()
            self._bgcolor = QColor(r * 7 // 8, g, b * 7 // 8)
    
        def paintEvent(self, event):
            painter = QPainter(self)
            painter.fillRect(event.rect(), self._bgcolor)
            super().paintEvent(event)