2

I have 9 QWidgets. Sometimes they are invisible. They are all in a 3x3 grid.

[0][3][6]
[1][4][7]
[2][5][8]

Now if for example widget 3 is made invisible, other widgets should should resize:

[   0   ][   6   ]
[  1 ][  4 ][  7 ]
[  2 ][  5 ][  8 ]

The same should happen vertically, basically all the empty space should be filled but I'm not sure how to do that. When I set a widget invisible, the empty space is not taken.

QGroupBox *parent = getParent();
QGridLayout *layout = new QGridLayout;
layout->setMargin(0);
layout->setMargin(5);
int w = parent->geometry().width();
int h = parent->geometry().height();
QSize min(w/3-2*layout->spacing(),h/3-2*layout->spacing());
QSize max(w,h);
for (int n = 0; n < 6; ++n)
{
    layout->setRowStretch(n,6);
    layout->setColumnStretch(n,6);
}

for (size_t n = 0, t = widgets.size(); n < t; ++n)
{
    QWidget *widget = widgets[n];
    widget->setMinimumSize(min);
    widget->setMaximumSize(max);
    widget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    layout->addWidget(widget);
}

Thanks in advance for the help.

fonZ
  • 2,428
  • 4
  • 21
  • 40
  • 2
    I've tried to implement the same behavior. I've successfully solved the issue by using `QVBoxLayout` to implement rows and `QLabel` to implement cell (row). Everything works from the box without tuning of geometry. – Gluttton Jun 11 '17 at 15:24
  • @Gluttton interesting, I thought about using QVBoxLayout and QHBoxLayout but I wasn't sure. Do you have an example of your implementation? – fonZ Jun 11 '17 at 15:28
  • 1
    Unfortunately I can't share it. But this is trivial implementation: something lile https://pastebin.com/th4mHWu0 . – Gluttton Jun 11 '17 at 15:37
  • 1
    @Gluttton Works like a charm, thanks a lot! Put it in an answer and I'll upvote it. – fonZ Jun 11 '17 at 16:13

3 Answers3

2

I have the similar experience. I used such widget to visualize dynamically changed configuration of device.

The required behavior can be achieved by using QVBoxLayout as row and QWidget ad cell (column). In my case I used custom widget derived from QLabel as cell. Everything works from the box without tuning of geometry.

Pseudo code:

// Inside widget's constructor (or createLayout function).
topLayout = new QVBoxLayout ();

aLayout = new QHBoxLayout ();
bLayout = new QHBoxLayout ();
cLayout = new QHBoxLayout ();

topLayout->addLayout (aLayout);
topLayout->addLayout (bLayout);
topLayout->addLayout (cLayout);

setLayout (topLayout);

...

// Add cell to corresponding row.
void add_cell (QWidget * cell)
{
    aLayout->addWidget (cell);
}
Gluttton
  • 5,739
  • 3
  • 31
  • 58
  • This will work for the case, which is shown in the question. However, fonZ has an additional requirement: The same should happen vertically. How do you handle the case when for example 1 and 4 are hidden? From what it is shown in the question, I understand, that 0 should then occupy the space of 1 and the half of 4 with 7 occupying the other half of 4. – scopchanov Jun 11 '17 at 16:45
  • @scopchanov, yes, you are right my solution only for "horizontal spawn". – Gluttton Jun 11 '17 at 16:54
  • 1
    which doesn't make it unusable in any way, of course. I am just curious if this with the vertical grow could be solved in a different maner than I've suggested. To be honest, I find using QGridLayout not so convenient as one might have expected. – scopchanov Jun 11 '17 at 17:03
2

First, remove the widget from the layout by iterating the layout and removing the item that holds the widget. While doing that you also collect the information about available cells. Then reinsert the widget with proper position and spans.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
1

As far as I know, there is no way to do that automatically. I would suggest you to keep a list of the widgets and reposition them by clearing the grid layout and populating it again each time a widget changes its visibility. I found out that only this way I can solve a similar task that I had (for rearranging the widgets in the grid) without creating a custom layout by subclassing QLayout.

scopchanov
  • 7,966
  • 10
  • 40
  • 68
  • No need to clear the layout. Layouts support removal of individual widgets. – Kuba hasn't forgotten Monica Jun 11 '17 at 16:28
  • Yes, of course they do. However, I found it easier to clear the layout first and then repopulate it. Especially with QGridLayout this should be the prefered strategy. – scopchanov Jun 11 '17 at 16:33
  • "this should be the prefered strategy" The way I read that is that it's preferred by you because you found it "easier. It really depends on the task at hand. – Kuba hasn't forgotten Monica Jun 12 '17 at 15:18
  • Totally agree. That is my personal preference. I find it easier, i.e. more readable, that way. For 9 objects, as in this case, it should not cause a performance issue. For large amount of objects the strategy might be different. So it depends on the task indeed. Btw, there is a difference between should (suggestive) and must (obligatory). No offence intended, of course, just a clarification! – scopchanov Jun 12 '17 at 15:28