Shrinking a Qt widgets to the minimum size they can become because of size constraints or child widgets is not a difficult task. In fact, it's simply one call to resize(0, 0) that does just that. Because even resizes by the programmer are bound to the usual constraints, this resizes to the smallest possible size.
But when trying this in practical situations, it might become tricky. Shrinking your widgets means it becomes smaller. A widget (or dialog, or window) usually becomes smaller after removing or changing stuff. You will notice, however, that after removing a widget, a call to resize(0, 0) will not resize your widget to the size it would occupy without the removed widget, but instead it behaves like the widget was still there. This is because the widget is not completely removed until the next processing of the message loop. There are two ways to make certain that the message loop is being processed. One is calling QApplication::processEvents(). The other is using a QTimer::singleShot() and doing the task you want to do in the provided slot. I've tried both in regards to shrinking the widget and noticed that using a singleShot is more flicker-free than calling processEvents(), at least on the Windows platform.
I've created a demo-application to visualize the problem and check which method works better on a certain platform. Here are some screenshots:
This is the window after opening the application. You can choose between directly shrinking the widget after removing the last button, using a singleShot() and using processEvents().
Two buttons have been added, the dialog has automatically grown.
The last button has been removed, resize(0, 0) has been called directly after removing the widget. You can see that the size is not appropriate, the space the button took is still there. Notice the wider gaps between the widgets.
The last button has been removed, resize(0, 0) has been called in a slot that was activated by a QTimer using a singleShot(). The size of the window is correct, no flicker was visible.
The last button has been removed, QApplication::processEvents() has been called before calling resize(0, 0). The size of the window is correct, but there was flicker visible.
You can download the source-code of the demo-appliction here and try it out yourself.
Hey, would it be possible to tag your Qt articles so there would be a qt rss feed that I could add to planetqt?
ReplyDeleteYup! Will do that for this and other related blog posts.
ReplyDeleteI'm always too lazy for tagging ;-)
Added :)
ReplyDeleteThere's also QWidget::adjustSize() and QLayout::setSizeConstraint(QLayout::SetFixedSize). ;)
ReplyDeleteFollowing what J-P Nurmi suggests, there's a nice example at
ReplyDeletehttp://wiki.qtcentre.org/index.php?title=Expanding_dialog
cheers!
Hello,
ReplyDeleteThank you very much for your code. On my Kubuntu Linux machine both singleShot and processEvents flicker (there is no difference in the amount of flicker). But adding the following line in the constructor removes the flicker:
m_layout.setAlignment(Qt::AlignTop);
Hey! great blog , your information tips and tricks,which you provided really gud ...this is gud way to provide the information..nice work
ReplyDeletegaurvi
orangy tech
You can reduce flickering by keeping a spacer with expanding size policy.
ReplyDeleteGreat!
ReplyDelete