18

How do I preview what the size of widgets in a window will be after the layout rules are applied, before I actually show() the widget window? It seems all sizes are 100x30 before that initial show() command. How do I go around that?

Mat
  • 202,337
  • 40
  • 393
  • 406
JasonGenX
  • 4,952
  • 27
  • 106
  • 198
  • MY own widget window class, examines the size of objects and adding dynamic widgets at construction time. I need to measure sizes of how things will look AFTER a layout at that phase. – JasonGenX Feb 10 '11 at 22:47

6 Answers6

10

The invalidate() worked for me.

Notice that if you do the following it would work as asked here (at least it seems to be fine in my code):

widget->show();
widget->layout()->invalidate();
widget->hide();

This doesn't show the widget on the screen since you don't relinquish control back to the queue until the hide() happens. In between, the invalidate() computes the correct positions.

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
  • On Qt 5.14 this doesn't work -- the Window flickers between the calls to `show()` and `hide()`. – Rotsiser Mho May 11 '23 at 17:40
  • @RotsiserMho Interesting... I thought you'd have to hit the event loop for any flickering to happen. Plus even in a multi-thread application the event loop (as far as I know) is not going to be managed but by the main thread. – Alexis Wilke May 11 '23 at 20:07
8

For me, the following worked:

window->layout()->update()
window->layout()->activate()

This probably does the same as Alexis' answer but it doesn't require showing-then-hiding the window.

JanKanis
  • 6,346
  • 5
  • 38
  • 42
  • This did the trick for me too! I was trying to center my window on the screen. It was consistently off until I added those two lines right before I centered the window. – Onlyjus Mar 18 '14 at 14:11
  • Sadly this is not working for me on Qt 5.14. – Rotsiser Mho May 11 '23 at 17:41
4

Use QWidget::sizeHint to get the desired size of the top level widget based on the sizeHints of all child widgets and layouts. Or call QWidget::adjustSize to actually run the layout and resize the entire widget tree. Note that adjustSize will limit top level windows to 2/3 of the screen so you may not get what you want for large windows.

3

You could try googling for "qt geometry before show" which shows a thread titled Force geometry update of hidden widget on qtcentre.org forum where you can read Wysota answer:

You can call invalidate() on the layout. It should recalculate itself then. If not then there is this secret attribute that convinces the widget it is being shown and then you should be able to force its layout to recalculate. But try other things first, this is not something very reliable.

and this

Qt::WA_WState_ExplicitShowHide set to true and Qt::WA_WState_Hidden set to false. Be sure to revert the values (especially the second one) before you actually show the widget on screen.

Piotr Dobrogost
  • 41,292
  • 40
  • 236
  • 366
2

I tried the various solutions posted by others (show&hide, update&activate, invalidate and WA_WState_ExplicitShowHide&WA_WState_Hidden) but none was correct with all the widgets I had to center BEFORE calling show() in my application. I spent hours digging and my problem was that incorrect sizes were cached inside QWidgetItemV2. A few minutes later I came up with this:

for(auto*child:widget->findChildren<QWidget*>()){child->updateGeometry();}
widget->updateGeometry();
Arnaud
  • 3,765
  • 3
  • 39
  • 69
1

Under PySide2, this is the solution that ended up being the ticket for my use case:

    self.setAttribute(Qt.WA_DontShowOnScreen, True)
    self.show()
    self.layout().invalidate()
    self.hide()
    self.setAttribute(Qt.WA_DontShowOnScreen, False)

This is effectively the same as the accepted answer. However, omitting the changes to the WA_DontShowOnScreen attribute would cause a window flicker on first show.

SoylentFuchsia
  • 1,181
  • 9
  • 8