I'm having a problem where I cannot deterministically tell when a layout takes place.
Simplified example:
I have a widget with two sub-widgets.
Top widget has expanding width and fixed height. Let's say the fixed height defaults to 50.
Bottom widget has expanding height and width
There's a vertical layout set up.
Let's say there's a button somewhere i can click to run code. The button is not on the widget itself to make things simple...
When the button is clicked, i do the following:
I measure the height of the bottom expandable widget. The height is 100.
I then "topWidget->SetMaximumHeight(100)", and "topWidget->SetMinimumHeight(100)"
I measure the height of the bottom expandable widget again. The height is still 100
But I see the bottom expandable widget change height!
this means that when I do step #3, the layout hasn't taken place yet. No matter what I do, update(), updateGeometry() - I cannot get the bottom widget to change height between step #2 and step #3.
The only way for me to resolve this is to have a timer wait, say 250ms, and then measure the height of the bottom widget -- and then It's always correct - meaning the re-layout took place correctly
This is a crazy/dirty solution, but I don't have another. Is there an API I am missing to allow me to deterministically, synchronously change the layout and query for the new size of affected widgets right after?
from user: alexisdm
Try calling QApplication::processEvents() between steps #2 and #3 (it should do what the timer allow the event loop to do)
Related
I have a QScrollArea (we'll call it myContainer) that contains and scrolls a child view (we'll call it myChildWidget). All works almost fine - when I change the height of myChildWidget dynamically in response to something, if the height exceeds that of myContainer (the QScrollArea), a vertical scroll bar pops into view, effectively narrowing myChildWidget since I've set it to resize its child using:
myContainer->setWidgetResizable(true);
The problem is that myChildWidget is not actually resized until later, rather than right when I set its new height or try resizing myContainer, so I can't do certain things depending on its new width without subclassing and putting in a whole bunch of extra code. Surely there's something I can call to get the QScrollArea to auto-resize its child right away, right? I can use:
QCoreApplication::processEvents();
but the problem with that is that it causes the widgets to flash and redraw when I'm not done setting things up. I've tried update(), updateGeometry(), and adjustSize(), both on the container and its child, and none work. Anything I'm missing? Thanks for any help.
When I maximize my window, I want to restrict a vertical layout (and the entire row below it also) so that it has a specific size (lets say a width of 200). How can I achieve this? Below is what I get now. The buttons are stretched too far. I want them to keep a width of 200.
To stop the buttons stretching, use the following steps in Qt Designer:
click on scrollArea in the Object Inspector
click on Break Layout on the toolbar
click on scrollArea in the Object Inspector
click on Lay Out in a Grid on the toolbar
click on scrollAreaWidgetContents in the Object Inspector
scroll down to the bottom of the Property Editor
change layoutColumnStretch to 0,1
These steps should remove an empty column from the scroll-area grid-layout, and make the second column stretch to take up the available space when the window is resized.
You just need to restrict the maximum width of all widgets (in this case the buttons) within the layouts of this grid column to the expected size, else they'll just keep expanding. You may also have to fiddle the horizontal size policy; I seem to remember that buttons were a bit tricky in this regard (or was that the height?), but can't test it right now.
The layout size contraint you tried only applies to the layout's direct parent widget, if it has one, which isn't the case for the vertical layouts here.
I have a QDialog subclass that contains a spacer as its only immediate child; all of the window’s UI elements are contained in the spacer. The user cannot change the window size directly, but UI elements will be shown or hidden as the user interacts with the window. I’d like the dialog to resize each time this happens so that the spacer (and the dialog itself) always takes up the minimum possible amount of space. How can I configure my dialog and my spacer to get the desired behavior?
(This question dealt with something similar, although in that case the user was able to resize the window. It was also not clear to me what the OP actually ended up doing in that case.)
You can resize the window to minimumSizeHint() after the number of widgets is changed :
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 after some widgets are hidden and some other are shown, just process the event loop for some iterations and then resize to minimum.
It's like :
for(int i=0;i<10;i++)
qApp->processEvents();
resize(minimumSizeHint());
A better solution 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.
void QWidget::adjustSize()
Adjusts the size of the widget to fit its contents.
I have an widget x with fixed size. Then at first I took a QScrollArea and then a QGridLayout which I set as the layout of scrollAreaWidgetContent. Then I started adding some widget x in the layout at (0,0), (0,1), (1,0), (1,1)... of grid layout. Then when I ran the program, strangely when I shrink the window vertically, the widgets overlap.
And as expected, when I increase the window size vertically, they are not overlapped anymore.
But strange thing is this problem does not occurring when I shrink window horizontally. For example,
My question is, why this is happening and more importantly, keeping in mind I want to use gridlayout, how to solve this problem?
As you said in your question:
Your widget has a fixed size, so the layout does not shrink them when there is no space left.
So the question is: what do you want to happen when you shrink the window?
If you want to shrink your widget you have to change the sizePolicy of your widgets from "Fixed" to "Preferred".
If you want to reduce the number of widgets in the layout, then you could add an event handler in the resize event and remove them
If you want to disallow the shrinking of the window, then you need to set the sizePolicy of the scrollarea to a fixed or minimumSize
My problem probably is very simple, but I have no idea how to solve it.
So, I have several widgets in vertical layout. Some of them in some moment should be invisible. I suppose this moment the control that has expanding vertical policy should increase its height but it never happens. Why? How to force it to change the size? So far there is only one way to do that - to change the size of window manually a little bit and only after it the widget changes its height.
When you make a widget invisible (i.e. call hide), also remove it from the layout (see removeWidget). That way all of the other widgets will automatically resize to make use of the extra space. Since you are only hiding the widget, its space is still reserved in the vertical layout.
Make use of insertWidget to maintain the layout ordering when transitioning a hidden widget back into view. Otherwise, addWidget would always place it at the bottom. This approach should be less complex than managing the sizes manually.
Try calling adjustSize() on the parent of the layout.
Have you tried setting the stretch on 1 for the widget you want to be expanded when others are hidden?
QBoxLayout::addWidget( my_widget, 1 );
When this widget is added with a stretch of 1 and the other widgets without stretch, this widget will expand to the available space. Maybe that will do the trick.