In a simple form I made a few buttons and put a horizontal layout. When mouse leaves the area one of the buttons, the last one, should be hidden. Using button->hide()
it works, but all the buttons are rearranged by the layout manager. What I want is that all other buttons remain in their positions. I tried replacing the widget with a widget placeholder and swapping the button and placeholder hide()
/show()
, calling placeholder->resize(button->size())
, but the layout manager doesn't respect the resize, and the placeholder is set with its minimum size. What is the best way to remove a widget and keep its space?
9 Answers
In Qt 5.2 it is possible to do the following:
QSizePolicy sp_retain = widget->sizePolicy();
sp_retain.setRetainSizeWhenHidden(true);
widget->setSizePolicy(sp_retain);
I earlier posted the same solution here:
How to make a Qt widget invisible without changing the position of the other Qt widgets?
(which seems to be a duplicate of this question).
I had the same issue.
I ended up adding a HorizontalSpacer (my layout was horizontal), which I initially set to 0-size and Fixed size policy. Then I used:
if (button_is_shown)
ui.horizontalSpacer->changeSize(0,0, QSizePolicy::Fixed, QSizePolicy::Fixed);
else
ui.horizontalSpacer->changeSize(1,1, QSizePolicy::Expanding, QSizePolicy::Fixed);
To fill in the space. Similarly, you could resize the spacer to the size of the button and keep it as Fixed QSizePolicy.
You could try putting the button to hide inside another widget, and try to make the other widget keep its size properly when the button is hidden. This might be a little difficult. A QStackedWidget has been suggested, and might be the way to go... it would be similar to the QWidget wrapper, except sizing might be easier.
Another option you could look at is inserting a spacer for the placeholder, and setting the spacer to a fixed size that is the button's size. (You'll need to update the size when the button's size changes). You should be able to show/hide those in pairs and make it work like you expect.
I would also try installing an event filter that overrides the original paint event, drawing a transparent background, and ignores most of the events that the widget should not respond to when it's invisible (probably all of them, except QResizeEvent
). When the widget becomes visible again, remove the event filter.
See QObject::installEventFilter(QObject*)
and QObject::removeEventFilter(QObject*)
.
Probably the simplest way to do it is to set maximum size of buttons to their size hint.
button->setMaximumSize(button->sizeHint());
This should keep the visible buttons the same size and not force them to expand when another is hidden. You will need to take care that if you change the text on the buttons, that you reset their maximum size, but you likely only do this in one place anyway. I believe something like this was done in one of the early chapters of the Qt book (but I don't have it in front of me, so I can't point you to the right place).