【问题标题】:Qt ScrollArea on widget messes up size and position of widget [Qt 5.1]小部件上的 Qt ScrollArea 弄乱了小部件的大小和位置 [Qt 5.1]
【发布时间】:2014-03-26 23:33:06
【问题描述】:

我是 Qt 新手,我想实现一个可以动态增长的可滚动小部件,例如通过在按下另一个按钮时向其中添加按钮。我尝试使用以下布局和代码来实现它:

scrollArea = new QScrollArea(ui->outerWidget);
scrollArea->setWidget(ui->innerWidget);
layout = new QVBoxLayout(ui->outerWidget);
ui->innerWidget->setLayout(layout);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

// code for PushButton to add buttons in innerWidget
void MainWindow::on_pushButton_clicked()
{
    QPushButton *button = new QPushButton("button"+QString::number( nameCounter ));
    nameCounter ++;
    ui->innerWidget->layout()->addWidget(button);
}

这个实现在我运行程序时有两个问题,首先是 innerWidget 出现不合适的位置(我在 Qt Creator 的设计模式中定义了它的位置),其次在布局中添加了许多小部件后,滚动条没有增长,但小部件会变小以适应布局:

another thread 中建议将 widgetResizable 设置为 true:

scrollArea->setWidgetResizable(true);

滚动条现在似乎可以工作了,但新问题是 innerWidget 变得非常小,因此几乎看不到:

那么,我怎样才能实现一个尊重设计大小和位置的可滚动小部件?

【问题讨论】:

    标签: qt layout widget scroll


    【解决方案1】:

    没有环境可以验证,但祝你好运。

    • 将scrollArea放置到目标位置,

      • 手动调用 SetGeometry,或
      • 以 ui 形式放置 QScrollArea,(如果是静态的则建议),或
      • 在您的目标位置放置一个小部件,并为其设置 QScrollArea 的父级,并将 QScrollArea 添加到其布局中,并将 QScrollArea 设置为展开。
    • 手动创建一个QWidget innerWidget 并通过QScrollArea::setWidget(*QWidget) 将其分配给scrollArea,尝试不同的大小策略innerWidget,例如“Preferred”。

    还要注意提到的 Qt 参考:void QScrollArea::setWidget ( QWidget * widget ) 设置滚动区域的小部件。 …… 请注意,您必须在调用此函数之前添加小部件的布局;如果您稍后添加它,则该小部件将不可见 - 无论您何时显示()滚动区域。在这种情况下,您以后也可以不显示()小部件。

    以上列出的解决方案,以下是您提到的问题的原因:

    • scrollArea->setWidget(ui->innerWidget);将一个widget设置为ScrollArea会改变ui->innerWidget的parenting和layout,所以以ui形式(在Qt Creater中)写的几何值将不再生效,这就是原因innerWidget 不合适。 ui->innerWidget 不再是outerWidget 的子对象,它的几何图形将跟随其新父对象(但不是scrollArea,QScrollArea 内部有一些棘手的布局”。需要说明的是,innerWidget 在这种情况下对定位scrollArea 没有帮助。

    • 在您的第一个代码片段中,小部件“scrollArea”是使用父 outerWidget 创建的,同样没有指定大小策略或布局或几何形状,因此默认情况下 scrollArea 将放置在父级的左上角“外部小部件”。要将 scrollArea 放置到目标几何体,您可以“手动设置几何体”或“将 innerWidget 指定为 scrollArea 的父级并展开 scrollArea”。显然后一种方法不能将ui->innerWiget分配给scrollArea->setWidget()。

    • scrollArea->setWidgetResizable(true); 使外部控件左上角的滚动区域“缩小”。这是因为,QScrollArea 不会随着它的内容而增加,它可以滚动显示它的所有内容,所以 QScrollArea 所需的大小可以尽可能小。一旦 'Resizable' 属性设置为“true”,QScrollArea 决定缩小到其最小必要大小,从而显示其滚动条和滚动按钮的大小......

    【讨论】:

    • 非常感谢,很好的回答!我的印象是 scrollArea 会得到 innerWidget 的几何形状,显然我错了。
    • 很棒的答案。我有一个表单布局,我直接将其添加为滚动区域的布局,但是行数太多,它会缩小到一切都看不见的地步。首先创建一个通用 QWidget,然后将我的布局添加到其中,然后将其添加为滚动区域的小部件,就像一个魅力!