PyQt6 – Dummy child class not showing when inheriting from QWidget (but shows when inheriting from QLabel)

Question:

I’m learning PyQt / Qt and I am facing a basic problem. I want to make a child class that inherits from QWidget but for some reason it does not show.

For trouble shooting, I’ve used a simple dummy child class.

from PyQt6.QtWidgets import QWidget, QApplication,QMainWindow, QLabel
import sys

class TestWidget(QWidget):

    pass

class TestLabel(QLabel):

    pass

app = QApplication(sys.argv)
w = QMainWindow()
w.resize(500,500)
w.setStyleSheet('background-color: white;')
w.show()

#frame = QWidget(w)     # SHOWS
frame = TestWidget(w)   # DOES NOT SHOW
#frame = TestLabel(w)   # SHOWS
frame.resize(200,200)
frame.setStyleSheet('background-color: red;')
frame.show()

app.exec()

In the code sample I have tested the following scenarios (by commenting out the other two options). The expected result is a red rectangle in the upper left corner:

  1. Using a simple QWidget; it shows
  2. Using a dummy child class of QWidget; it does not show
  3. Using a dummy child class of QLabel; it shows

The code is really simple so I’m struggling to understand what’s going on.

I’m using Python 3.11 on Mac OS Ventura (Apple Silicon).

Any ideas?

Asked By: Bearify

||

Answers:

It’s because the QWidget class is the base class of all widgets and designed to have no drawing(painting) logic in it even for the background by default. In most cases of deriving from the QWidget, you either implement a custom drawing logic by overriding paintEvent() or use it as an invisible event receiver.

The behavior that a QWidget instance(not a derived one) with the background specified by the style sheet draws the background is documented in the official Qt wiki at this, or in the official reference at this.(The second link was given by musicamante.) But it is rather controversial because it should not draw the background in the view point that the QWidget does not have drawing logic in paintEvent(), but it should draw the background in the view point that an HTML element with the CSS background is drawn with the background.

If you want to draw the background without overriding paintEvent(), use the autoFillBackground property like this.

from PyQt6.QtCore import Qt
from PyQt6.QtGui import QPalette
...

class TestWidget(QWidget):
    pass

...
frame = TestWidget(w)
frame.setAutoFillBackground(True)
pal = QPalette()
pal.setColor(QPalette.ColorRole.Window, Qt.GlobalColor.red)
frame.setPalette(pal)
...

Of course, simply deriving your class from the QFrame or QLabel will be much easier.

Answered By: relent95
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.