I want to arrange a bunch of QPushButtons in a layout so they will wrap horizontally (like text). I'm trying to use the Qt example FlowLayout in PySide2.
I've posted a simple example revision 2 here
(This is based on the official example here, which is why I'm so perturbed it doesn't work well.)
Specifically, it works well when the window is large enough:
but doesn't prevent the window from being shrunk down small, whereas a VBoxLayout or GridLayout would:
I think the minimum size should depend on the current width. This should be a minimum size:
and so should this:
How can I get the layout to prevent its parent from being shrunk so small that its contents aren't visible?
sizeHint() and minimumSize() always return the size of a single item, which I thought was the problem. However if I rewrite them to take into account all items at the current layout width, it doesn't matter, because both are only called once, when I create and populate the layout.
My best idea so far is to call update() from heightForWidth(), roughly this:
def heightForWidth(self, width):
oldWidth = self.geometry().width() - 2 * self.contentsMargins().top()
oldHeight = self.doLayout(QtCore.QRect(0, 0, oldWidth, 0), True)
height = self.doLayout(QtCore.QRect(0, 0, width, 0), True)
print 'heightForWidth', width, oldWidth, height, oldHeight
if height != oldHeight:
self.update()
return height
full sample with changes to minimumSize and doLayout is revision 3. It works sometimes, but has several problems:
When the layout is first created there are constant calls to update(). I think the call to update() triggers a call to heightForWidth() and for some reason the width passed in is not close to the "oldWidth" that I calculate until I resize the window, even by a single pixel.
As soon as I resize the window, calls to heightForWidth() stop completely, and minimumSize() stops being called, and I can no longer resize my window smaller than the last size calculated. I've no idea why.
(Much less important) self.geometry().width() - 2 * self.contentsMargins().top()
does not return the width that was last passed to heightForWidth (even when top/bottom/left/right margins are identical), though I took it from other code in the example. This doesn't usually matter but at certain widths it causes a flurry of calls to update()
I suppose I'm doing it all wrong. Can it be done right?
I've ported the original/official example to PySide2 now, and it works without changes. I'm not sure what was preventing it from working before.