views:

154

answers:

3

I am using a QVBoxLayout to arrange a vertical stack of widgets. The QVBoxLayout is contained within a QScrollArea. I want some of the widgets to be initially hidden and only show up when a check box is checked. Here is an example of the code I'm using.

MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
    QVBoxLayout *layout = new QVBoxLayout(this);

    QLabel *labelLogTypes = new QLabel(tr("Log Types"));

    m_checkBoxCsv = new QCheckBox(tr("&Delimited File (CSV)"));
    m_labelDelimiter = new QLabel(tr("Delimiter:"));
    m_lineEditDelimiter = new QLineEdit(",");
    checkBoxCsv_Toggled(m_checkBoxCsv->isChecked());
    connect(m_checkBoxCsv, SIGNAL(toggled(bool)), SLOT(checkBoxCsv_Toggled(bool)));

    QHBoxLayout *layoutDelimitedChar = new QHBoxLayout();
    layoutDelimitedChar->addWidget(m_labelDelimiter);
    layoutDelimitedChar->addWidget(m_lineEditDelimiter);


    m_checkBoxXml = new QCheckBox(tr("&XML File"));
    m_checkBoxText = new QCheckBox(tr("Plain &Text File"));


    // Now that everything is constructed, put it all together
    // in the main layout.
    layout->addWidget(labelLogTypes);

    layout->addWidget(m_checkBoxCsv);
    layout->addLayout(layoutDelimitedChar);

    layout->addWidget(m_checkBoxXml);
    layout->addWidget(m_checkBoxText);

    layout->addStretch();
}


MyWidget::checkBoxCsv_Toggled(bool checked)
{
    m_labelDelimiter->setVisible(checked);
    m_lineEditDelimiter->setVisible(checked);
}

I want m_labelDelimiter and m_lineEditDelimiter both to be initially invisible and I want their visibility to toggle with the state of m_checkBoxCsv. When they become visible, I would like the layout to expand vertically to accommodate them.

This code achieves the functionality I desire, but it doesn't seem to reserve space for the two initially hidden widgets. When I check the checkbox, they become visible, but everything is kind of scrunched to accommodate them.

If I leave them initially visible, everything is laid out just the way I would like it. Is there any way to make the QVBoxLayout reserve space for these widgets even if they're initially invisible?

If I don't put this widget into a QScrollArea, then this code works exactly as I want it to. What is the deal with the QScrollArea?

+1  A: 

You could try adding a spacer item into your layoutDelimitedChar layout with predefined max height, smth like this:

QHBoxLayout *layoutDelimitedChar = new QHBoxLayout();

layoutDelimitedChar->addSpacerItem(new QSpacerItem(0, 33, QSizePolicy::Maximum, QSizePolicy::Maximum));

layoutDelimitedChar->addWidget(m_labelDelimiter);
layoutDelimitedChar->addWidget(m_lineEditDelimiter);

hope this helps, regards

serge_gubenko
+2  A: 

There are a few ways you could do this.

1) Add your initially-invisible widgets to a different widget, and put that other widget into the place you need the space. Have the outer widget set to the same size as the inner one. When you hide/show the inner widget, it will have no affect on the size of the outer widget, and so not cause any of the layout to be resized.

2) Add another widget alongside the ones you want to have invisible, of the same size. Whenever you show an invisible widget, you hide the corresponding visible one. This will effectively swap two widgets of the same size, so shouldn't cause the layout to shift (although it will be recalculated).

3) Put a stacked widget where you want the invisible ones to be, and put the invisible widget on one page, with no widgets on another page. Size the stacked widget appropriately. Then you can change the page of the stacked widget based on whether you want the inner widget visible or not. Note that this is more cumbersome for just one widget shown/hidden, but if you have three or more mutually-exclusive options for what to show, it starts to become more feasible.

The big aspect in all of this is sizing. You could adapt my suggestions to account for sizing somehow as well, but it is more difficult if you want the invisible widget to also be dynamically sized.

Caleb Huitt - cjhuitt
+1  A: 

I apologize for not being totally clear in my original question. It turns out that the problem seems to have been related to this widget having been contained within a QScrollArea. When I called scrollArea->setWidgetResizable(true), things started to work perfectly.

Thanks for your suggestions, serge and Caleb.

Skinniest Man