38

Basically I've got a QGridLayout with a few widgets in it. The important ones are 2 labels, which I use for drawing images to the screen. Well, if the user wants, he can change the resolution of the incoming images, thus, forcing the Labels to resize.

Let's assume the initial size of the label is 320x240. The user changes the VideoMode to 640x480, the label and the entire GUI resizes perfectly. But when the user switches back to 320x240, the label shrinks, but the Layout/Window does NOT.

I've played around with sizePolicies and sizeHints, and resize(0,0), but nothing did the trick. Could somebody help me with this?

Here some screenshots to clarify the problem:

Here, everything is okay still, 640 x 480 resizes perfectly but here, the layout is too big.

NG_
  • 6,895
  • 7
  • 45
  • 67
Hafnernuss
  • 2,659
  • 2
  • 29
  • 41
  • 1
    I had a problem where a widget down in the widget tree resized, but the top widget didn't update its size. The solution was to emit a custom signal in this resizing widget, and connect it to a custom slot in the main window with a `Qt::QueuedConnection`. This slot then just does a `resize(sizeHint())`. – hochl Oct 28 '20 at 17:48

4 Answers4

74

You need to set the size constraint of the layout holding all your widgets to "SetFixedSize". Although the name doesn't sound like it will work, it ensures that your layout will only use the space it needs. You will not have the problem like you do in your second screenshot.

Example:

mainLayout.setSizeConstraint(QLayout::SetFixedSize);
user929404
  • 2,153
  • 1
  • 22
  • 27
  • 5
    Thank you! This saved me another couple of hours searching and debugging caused by this horrible naming. Why does SetFixedSize imply "automatic resize to minimum size" which is semantically NOT a fixed size because the minimum size depends on the (potentially dynamic) sizes of the widget's contents? Is there ANY explanation for this? – hgross Aug 15 '14 at 18:45
  • 1
    The name does not make much sense, and its been a while since I worked with Qt, so I don't recall how I found this out. But this problem bugged me for a while. Glad it helped you – user929404 Aug 17 '14 at 16:38
  • This appears to work for everything except for QScrollArea widgets. Do you know a solution for that? – Assimilater May 15 '15 at 16:29
  • 1
    nvm, I found I can set it to ignored and let size policy of child widgets dictate sizing (see last response here: http://www.qtcentre.org/threads/7593-QScrollArea-and-resizing) – Assimilater May 15 '15 at 16:34
  • nvm nvm, it doesn't expand anymore to fit child contents. Maybe I need to ask a separate question... – Assimilater May 15 '15 at 16:47
  • 1
    Nice, this was such a long search to get this right! – Ben Oct 13 '15 at 13:31
  • Interestingly, `setSizeConstraint` did not solve the problem for me in `PySide6`, see https://stackoverflow.com/q/73789953/880783. `QTimer.singleShot(0, self.adjustSize)` was the solution there. – bers Sep 21 '22 at 07:12
11

QLayout::setSizeConstraint(QLayout::SetFixedSize) solves this problem well when you prefer keeping your widget's size fixed at all times--that is, if you'd like it to always be fixed to its "packed" size (which may still vary as the child widgets change size). That is what the "fixed" means there: "fixed" to the correct size, even as the latter varies. (In Qt terms, what I'm calling the "packed" size is simply the widget's sizeHint.)

But a constraint may be too strong a solution in some instances. In particular, if you apply it to a top-level window, then the user will not be free to resize the window. If you don't like that, you can instead perform the "set size to sizeHint" operation instantaneously each time it's needed, rather than imposing it as an unrelenting constraint. The way to do that is to call QWidget::adjustSize().

http://doc.qt.io/qt-5/qwidget.html#adjustSize

Note that if the container whose children are changing size is not the top-level window, then adjustSize() may have to be called recursively on the container and its parents. (In my case I had to do that, anyway. I also tried the size-constraint scheme, and found that applying the constraint at only the topmost level was successful in compacting all levels. I haven't enough knowledge of Qt to comment usefully on these observations, so I merely share them.)

mjwach
  • 1,174
  • 2
  • 9
  • 25
2

You need to store the original size of your widget parent window before applying any changes to the layout and restore it when the user switches back to the original.

Notice that you need to work with the widget parent window size and not the widget parent size.

in your widget before applying the layout changes:

minimumWindowSize = this->window().size();

when you finished reorganizing the widget to the compact size

this->window().resize(minimumWindowSize);
Pierluigi
  • 2,212
  • 1
  • 25
  • 39
  • thank you, i will try that in a few minutes. the fact is, there are many different combinations of resolutions, from 320x240 up to 1280x1024. It would take up to 10 size configurations. Is there no way Qt does this automatically? – Hafnernuss Feb 21 '13 at 07:45
  • I did not test it, but you might try by only storing the minimum size (or even providing a null size). If I am correct QT should automatically increase the window size to the minimum value to display all the contained widgets – Pierluigi Feb 21 '13 at 13:22
1

So that is exactly what i'm doing in mu project. Resolution os doesn't matter. I have only to have a widget for rendering video, or image in your case.

void MainWindow::resizeEvent(QResizeEvent* event)
 {
   QMainWindow::resizeEvent(event);
   if ((player != 0) && ((player->isPlaying()) || player->isLoaded() || player>isLoaded())){
     renderer->resize(ui->mainVideoWidget->width(),ui->mainVideoWidget->height());
     resizeFilter();

 }
}
AntonD
  • 108
  • 12