When I used a custom Widget as the CentralWidget for QMainWindow in PyQt6, there was a gap between the CentralWidget and the QMainWindow? I wonder why that is.Here's my code:
from PyQt6.QtWidgets import QApplication, QWidget, QMainWindow, QLabel, QHBoxLayout
import sys
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self._layout = QHBoxLayout(self)
self.label = QLabel("hello")
self.label.setStyleSheet("QLabel {color: white;}")
self._layout.addWidget(self.label)
self.setStyleSheet("background-color: black; color: white;")
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# When using custom widgets, there is a gap
self.central_widget = MyWidget()
# When using Qwidget, there is no gap
# self.central_widget = QWidget()
# self.central_layout = QHBoxLayout()
# self.central_layout.addWidget(QLabel("hello"))
# self.central_widget.setLayout(self.central_layout)
self.setCentralWidget(self.central_widget)
# self.central_widget.setStyleSheet("background-color: black; color: white; border: none;")
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec())
I want to know why there is a difference between using a custom widget and using a QWidget, and how to fix it.
You are misinterpreting the result.
In your custom subclass you are setting the following stylesheet:
background-color: black; color: white;
This results in the following:
What you see is not the background of the widget, it's the background of the label. The gap that you see near the edges is the layout margin.
The situation is more clear if you specify the alignment on the label; when adding a child to a layout, the layout will try to make the widget occupy as much space available within the "layout cell", but if the alignment is specified it will only use the widget's size hint.
Try to do the following:
self._layout.addWidget(self.label, alignment=Qt.AlignCenter)
And you will see this:
Theoretically, you could try to nullify the layout margin:
self._layout.setContentsMargins(0, 0, 0, 0)
In reality, that is not the correct solution, because:
So, in order to make the widget have its own background you must use proper syntax in the QSS (with selector types) and ensure that the parent widget actually paints its background, which can be achieved either by setting the Qt.WA_StyledBackground
attribute, or by implementing the paintEvent()
.
class MyWidget(QWidget):
def __init__(self):
...
self.setStyleSheet("MyWidget { background-color: black;} ")
self.setAttribute(Qt.WA_StyledBackground)
Alternatively:
class MyWidget(QWidget):
def __init__(self):
...
self.setStyleSheet("MyWidget { background-color: black;} ")
def paintEvent(self, event):
qp = QStylePainter(self)
opt = QStyleOption()
opt.initFrom(self)
qp.drawPrimitive(QStyle.PE_Widget, opt)