Search code examples
python-3.xbackgroundpyqt5qwidgetqtstylesheets

Why doesn't this custom QWidget display correctly


I'm retrying this question with a much better code example.

The code below, in its current form, will display a green shaded QWidget in a window, which is what I want. However, when commenting out the line:

self.widget = QWidget(self.centralwidget)

and uncommenting,

self.widget = Widget_1(self.centralwidget)

the green box doesn't display. The Widget_1 class is a simple subclass of QWidget, so I'm trying to wrap my head around where the breakdown is occurring. There are no error messages, and the print("Test") line within the Widget_1 class is outputting just fine, so I know everything is being called properly.

I'm not looking to use any type of automated layouts for reasons I don't need to go into here. Can you help me to understand why the green rectangle isn't displaying, and what correction I would need to make in order to utilize the Widget_1 class?

from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget
from PyQt5.QtCore import QRect
import sys

class Main_Window(object):
    def setupUi(self, seating_main_window):
        seating_main_window.setObjectName("seating_main_window")
        seating_main_window.setEnabled(True)
        seating_main_window.resize(400, 400)

        self.centralwidget = QWidget(seating_main_window)
        self.centralwidget.setObjectName("centralwidget")

        ###########  The following two lines of code are causing the confusion  #######

        #  The following line, when uncommented, creates a shaded green box in a window
        self.widget = QWidget(self.centralwidget)  # Working line

        #  The next line does NOT create the same shaded green box.  Where is it breaking?
        # self.widget = Widget_1(self.centralwidget) # Non-working line

        self.widget.setGeometry(QRect(15, 150, 60, 75))
        self.widget.setAutoFillBackground(False)
        self.widget.setStyleSheet("background: rgb(170, 255, 0)")
        self.widget.setObjectName("Widget1")

        seating_main_window.setCentralWidget(self.centralwidget)

class Widget_1(QWidget):
    def __init__(self, parent=None):
        super().__init__()
        self.setMinimumSize(10, 30)  # I put this in thinking maybe I just couldn't see it
        print("Test")   # I see this output when run when Widget_1 is used above

class DemoApp(QMainWindow, Main_Window):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

if __name__ == '__main__':  # if we're running file directly and not importing it
    app = QApplication(sys.argv)  # A new instance of QApplication
    form = DemoApp()  # We set the form to be our ExampleApp (design)
    form.show()  # Show the form
    app.exec_()  # run the main function

Solution

  • Accoriding to this Qt Wiki article:

    you must implement paintEvent in a custom QWidget subclass in order to use stylesheets. Also, since the widget is not part of a layout, you must give it a parent, otherwise it will not be shown. So your Widget_1 class must look like this:

    from PyQt5.QtWidgets import QStyleOption, QStyle
    from PyQt5.QtGui import QPainter
    
    class Widget_1(QWidget):
        def __init__(self, parent=None):
            super().__init__(parent) # set the parent
            print("Test")
    
        def paintEvent(self, event):
            option = QStyleOption()
            option.initFrom(self)
            painter = QPainter(self)
            self.style().drawPrimitive(QStyle.PE_Widget, option, painter, self)
            super().paintEvent(event)