4

I'm using a subclass of QMainWindow, in which I declared a central widget. This widget contains, among other things, a QGridLayout, which holds a set of buttons. The amount of buttons can grow or shrink, depending on the user's input. The spacing is set to zero, so that all buttons are clumped together. By default, it looks like this:

Layout by default

If the amount of buttons is increased, the grid and window will grow too just fine; if, however, the amount of buttons is reduced, it will look like this:

Layout done wrong

Now I would like to resize the window/layout/widget so that all buttons may use the minimal space. I've tried various things, but all to no avail. I had a look at this and this question, as well at various threads in the Qt board, but none of them worked for me.

My layout is build as follows:

self.grid = QtGui.QGridLayout()
self.grid.setSpacing(0)

hBox = QtGui.QHBoxLayout()
hBox.addWidget(...)

vBox = QtGui.QVBoxLayout(self.widget)
vBox.addLayout(hBox)
vBox.addLayout(self.grid)

self.setCentralWidget(self.widget)

I tried resizing it with ...

self.widget.layout().activate()
self.resize(self.minimumSize())
# self.resize(self.sizeHint())

... and various other methods. I also tried setting the size policy of my window and grid.

Steffen
  • 3,999
  • 1
  • 23
  • 30

3 Answers3

5

You can resize the window to minimumSizeHint() after the number of widgets is changed :

self.resize(minimumSizeHint())

This will shrink the window to minimum size. But you should consider that the minimum size is not computed until some events are processed in the event loop. So when the number of buttons are changed, just process the event loop for some iterations and then resize to minimum.

It's like :

for i in range(0, 10):
      QApplication.processEvents()

self.resize(minimumSizeHint())

Another option is to single shot a QTimer which calls a slot in which you resize the window to minimum. This way when you resize the window, the minimum size hint is computed correctly.

Nejat
  • 31,784
  • 12
  • 106
  • 138
  • Thanks a bunch! I actually tried `self.resize(minimumSizeHint())`, but I didn't know that I also needed to process some events. This seems sort of “hackish” to me, but it works. – Steffen Feb 23 '15 at 10:57
  • I recommend to use the second approach (single shot a timer) – Nejat Feb 23 '15 at 13:57
1

Though this was already answered, I found a very simple, elegant solution here. It was hard to find because the question is for this issue in Qt not PySide. You will have to translate it to PySide but it's really simple.

Essentially you want to set the size constraint of the layout you want to have automatically resized to QtGui.QLayout.SetFixedSize like so:

vBox = QtGui.QVBoxLayout(self.widget)
vBox.setSizeConstraint(QtGui.QLayout.SetFixedSize)

The code is not intuitive AT ALL but it works.

PyHP3D
  • 88
  • 10
0

for those who, like me, don't immediately get how to use the QTimer:

def function_with_blown_window_size(self)
    ...
    # 1 ms was too low for a refresh -> singleShot timer with 10ms delay
    QTimer.singleShot(10, self.window_size_readjust)

def window_size_readjust(self):
    self.adjustSize()                     # worked in my case
    #self.resize(self.minimumSizeHint())  # alternative worked equally well
Patrick C
  • 1
  • 3
  • Please don't add "thank you" as an answer. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation), you will be able to [vote up questions and answers](https://stackoverflow.com/help/privileges/vote-up) that you found helpful. - [From Review](/review/late-answers/31455445) – aaossa Apr 05 '22 at 13:45