How to Set QMainWindow Size?
-
OK, so here's another related frustration. My real code persists the state of the checkable action into a settings file. On startup it builds the UI and then if the action is checked hides the lower widget(s). This is all in the main window constructor. It then goes on to restore the reduced size main window using MainWindow::restoreGeometry(geometry) also from the settings file stored at shutdown with QMainWindow::saveGeometry(). This shows the correctly sized main window. If I then toggle the action twice the main window size then is bigger. This is really annoying. Why does MainWindow::restoreGeometry() work in the constructor before the first QMainWindow::show() and yet after that neither MainWindow::restoreGeometry(), nor QMainWindow::resize(), nor any other way of trying to set the size, I have tried so far, work correctly.
I have tried removing the lower widget(s) from the layout. I have tried hiding the whole main window before making the size adjustments and showing again afterwards (although I guess this is a no-op as i don't get into the event loop between the calls).
I must be missing the necessary incantation to make these sizing member functions work correctly.
-
@Cobra91151 Note also that this misbehaviour is the same on Windows, Linux, and macOS, so I don't think it is anything to do with native control renderings. It is something in Qt that is causing hidden widgets to influence the minimum size of a window when they should not.
-
Hidden widgets are not used by the sizeHint() calculation. Still no example which shows the opposite.
-
@Christian-Ehrlicher why is no one seeing this issue?
- Build my example above.
- Run it.
- Click the checkable menu item to move to the single widget display.
- Shrink the window to its minimum size using the mouse.
- Click the checkable menu item to move to the dual widget display.
- Click it again to move back to the smaller single widget display.
At this point the window is larger that it was shrunk to before. Why? The code calls resize with the smaller size but Qt still somehow accounts for the hidden widget. MainWIndow::restoreGeometry() does the same.
-
Ok, it took a while to understand what's going on here.
When you hide the widget, the main window as it's parent still has the old minimum height set which includes the (now hidden) widget. Therefore you can't resize the main window to the smaller saved size. You have to wait until the main window is notified about the hidden widget and it's minimum size is adjusted.void do_resize (bool checked) { auto s = size (); hideable_edit_->setVisible (!checked); qDebug() << "Current minimum size:" << minimumHeight() << saved_size_; if (saved_size_.isValid ()) { desired_size_ = saved_size_; } saved_size_ = s; // save for when we flip back } bool event(QEvent *e) override { auto ret = QMainWindow::event(e); if (e->type() == QEvent::LayoutRequest) { if (desired_size_.isValid()) { auto s = desired_size_; desired_size_ = QSize(); resize(s); } } return ret; } QSize desired_size_;
-
Thanks for taking the time to work that out @Christian-Ehrlicher, it works perfectly with restoring the size and also with restoring the whole window geometry which was my actual use case. I knew there would be an incantation that did this but finding it would have taken me a lot longer than the attempts I had made so far.
Looks to me that the Qt logic should be either giving higher priority to resize invocations, or it should be deferring the actual resize until after the layout change has been done. I'll bet it is a nasty chicken and egg, which comes first, situation.
-
The problem is the OS - until the OS does not tell us that the widget is really hidden or resized we have to wait. And all this stuff is async.