Artem
Artem

Reputation: 597

QWidget becomes invisible on layout assignment

I'm making a custom window using QGridLayout to place window elements: like title bar, size grip, etc.

When I set any layout to my widget it doesn't show up on a start. If I set .setVisible(True) it works nice.

So the question is: why does it happen, why widget becomes invisible on layout assignment? Is that some kind of a bug or so it is conceived?

Widget file is:

from PySide2 import QtWidgets, QtGui, QtCore


class QCustomWindow(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.background_color = QtGui.QColor(23, 23, 34)

        self._initUI()

    def _initUI(self):
        self.setWindowFlag(QtCore.Qt.FramelessWindowHint)

        print(self.isVisible())
        #self.setVisible(True)

        # Is visible without layout
        self.setLayout(QtWidgets.QGridLayout())

        self.layout().setMargin(0)
        self.layout().setSpacing(0)
        # ---------------------------------------

    def showEvent(self, event: QtGui.QShowEvent):
        self.centerOnScreen()

    def paintEvent(self, event: QtGui.QPaintEvent):
        painter = QtGui.QPainter(self)

        painter.setBrush(self.background_color)
        painter.setPen(QtCore.Qt.NoPen)

        painter.drawRect(0, 0, self.width(), self.height())

    def centerOnScreen(self):
        screen = QtWidgets.QDesktopWidget()
        screen_geometry = screen.screenGeometry(self)

        screen_center_x = screen_geometry.center().x()
        screen_center_y = screen_geometry.center().y()

        self.move(screen_center_x - self.width() // 2,
                  screen_center_y - self.height() // 2)

App file is:

from PySide2 import QtWidgets
from QCustomWindow import QCustomWindow
import sys


app = QtWidgets.QApplication(sys.argv)

window = QCustomWindow()
window.show()

sys.exit(app.exec_())

Upvotes: 1

Views: 148

Answers (1)

eyllanesc
eyllanesc

Reputation: 243955

Qt does not update the geometry unless necessary or force him to do it, and it does this for efficiency reasons. So if the setVisible(True) or equivalent method is not called then the geometry will not change.

By not calling setVisible(True) then the size is recalculated when the parent widget is visible, and at that moment the widget analyzes the information of the QSizePolicy, QLayouts, etc. In your particular case the one that has the preference has the layout, and the layout calculates the size based on the widgets that are added to it but in your case it has no added widgets so the geometry calculated by the layout is 0x0 making it not visible for our sight. So if you add widgets to the QGridLayout you won't see that problem.

But if you call setVisible(True) the geometry is calculated at that moment, since there is no layout at that moment, the sizeHint is used, which by default is 640x480 and is therefore visible. And when the layout is established the container size is equal to the maximum of the previous size and the size provided by the layout.

Summary:

  • why widget becomes invisible on layout assignment?

    If there is a layout set in a widget, then the size of the container widget will be the size determined by the widgets assigned to the layout, which in your case, since there are none, the size is 0x0.

  • Is that some kind of a bug or so it is conceived?

    No, it is not a bug but an expected behavior. Add widgets or set a size to show the window.

Upvotes: 2

Related Questions