【问题标题】:Reserve space for initially hidden widget in QVBoxLayout within QScrollArea为 QScrollArea 内 QVBoxLayout 中最初隐藏的小部件保留空间
【发布时间】:2011-02-12 15:12:10
【问题描述】:

我正在使用 QVBoxLayout 来排列垂直堆栈的小部件。 QVBoxLayout 包含在 QScrollArea 中。我希望某些小部件最初是隐藏的,并且仅在选中复选框时才显示。这是我正在使用的代码示例。

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);
}

我希望 m_labelDelimiterm_lineEditDelimiter 最初都是不可见的,并且我希望它们的可见性随着 m_checkBoxCsv 的状态而切换。当它们变得可见时,我希望布局垂直扩展以容纳它们。

这段代码实现了我想要的功能,但它似乎没有为最初隐藏的两个小部件保留空间。当我选中复选框时,它们变得可见,但一切都被挤压以适应它们。

如果我让它们最初可见,一切都会按照我想要的方式布置。有没有办法让 QVBoxLayout 为这些小部件保留空间,即使它们最初是不可见的?

如果我不将此小部件放入 QScrollArea,那么此代码将完全按照我的意愿工作。 QScrollArea 是怎么回事?

【问题讨论】:

    标签: qt layout visibility


    【解决方案1】:

    有几种方法可以做到这一点。

    1) 将您最初不可见的小部件添加到不同的小部件,然后将该其他小部件放入您需要空间的位置。将外部小部件设置为与内部小部件相同的大小。当您隐藏/显示内部小部件时,它不会影响外部小部件的大小,因此不会导致任何布局调整大小。

    2) 在您希望隐藏的小部件旁边添加另一个大小相同的小部件。每当您显示一个不可见的小部件时,您都会隐藏相应的可见小部件。这将有效地交换两个相同大小的小部件,因此不会导致布局发生变化(尽管会重新计算)。

    3) 将堆叠的小部件放在您希望不可见的位置,并将不可见的小部件放在一个页面上,另一页上没有小部件。适当调整堆叠小部件的大小。然后,您可以根据是否希望内部小部件可见来更改堆叠小部件的页面。请注意,这对于仅显示/隐藏一个小部件会更加麻烦,但如果您有三个或更多互斥选项来显示什么,它开始变得更加可行。

    所有这一切的重要方面是尺寸。您也可以调整我的建议以以某种方式考虑大小,但如果您希望不可见的小部件也被动态调整大小,那就更困难了。

    【讨论】:

      【解决方案2】:

      对于我最初的问题没有完全清楚,我深表歉意。事实证明,问题似乎与该小部件包含在 QScrollArea 中有关。当我打电话给scrollArea->setWidgetResizable(true) 时,一切都开始正常了。

      感谢您的建议,Serge 和 Caleb。

      【讨论】:

        【解决方案3】:

        您可以尝试将 spacer 项目添加到您的 layoutDelimitedChar 布局中,并使用预定义的最大高度,就像这样:

        QHBoxLayout *layoutDelimitedChar = new QHBoxLayout();
        
        layoutDelimitedChar->addSpacerItem(new QSpacerItem(0, 33, QSizePolicy::Maximum, QSizePolicy::Maximum));
        
        layoutDelimitedChar->addWidget(m_labelDelimiter);
        layoutDelimitedChar->addWidget(m_lineEditDelimiter);
        

        希望这会有所帮助,问候

        【讨论】: