Search code examples
pythonpyqtpyqt5qgridlayout

QGridLayout doesn't update when contents is resized?


I am trying to use a QGridLayout to hold resizable widgets, but when I resize them it doesn't work, the QGridLayout cells stay the same size...

Here is a minimal working example of the scenario causing me confusion. Double clicking the red squares should increase their size:

from PyQt5 import QtGui, QtWidgets
from PyQt5.QtCore import QSize, Qt
from PyQt5.QtWidgets import QSizePolicy
import sys

class Rect(QtWidgets.QFrame):
    def __init__(self, width, height):
        super().__init__()
        self.w = width
        self.h = height
        self.setStyleSheet("background-color: red")

    def mouseDoubleClickEvent(self, a0: QtGui.QMouseEvent):
        self.w *= 2
        self.h *= 2

        print(self.sizeHint())

    def sizeHint(self):
        return QSize(self.w,self.h)

    def minimumSizeHint(self):
        return self.sizeHint()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    gridLayout = QtWidgets.QGridLayout()

    gridLayout.addWidget(Rect(100,100), 0, 0, 1, 1)
    gridLayout.addWidget(Rect(100,100), 1, 1, 1, 1)
    gridLayout.addItem(QtWidgets.QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding), 2, 2, 1, 1)

    container = QtWidgets.QFrame()
    container.setLayout(gridLayout)

    container.resize(600,600)
    container.show()
    sys.exit(app.exec_())

Solution

  • If you want the sizeHint() change to be notified to the layout you must use the updateGeometry() method:

    def mouseDoubleClickEvent(self, event):
        self.w *= 2
        self.h *= 2
        self.updateGeometry() # <---
        super(Rect, self).mouseDoubleClickEvent(event)
    

    On the other hand, if you change the size of the window it will not change the size of the Rect since the QSpacerItem will occupy all the size that it can.