1

I'm new with Qt and I want to implement a scrollable widget which can grow dynamically, e.g. by adding buttons into it when another button is pressed. I try to implement it using the following layout and code:

enter image description here

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

This implementation has two problems when I run the program, first the innerWidget appears out of place (I define its position in Qt Creator's Design mode) and second after many widgets are added in the layout the scroll bar is doesn't grow, but instead the widgets are become smaller to fit into the layout:

enter image description here

In another thread it was suggested to set widgetResizable to true:

scrollArea->setWidgetResizable(true);

The scroll bar seems to work now but the new problem is that the innerWidget becomes very small so it is barely visible:

enter image description here

So, how can I achieve a scrollable widget that will respect the size and position of the design?

Community
  • 1
  • 1
Vasilis
  • 2,721
  • 7
  • 33
  • 54

1 Answers1

5

have no environment to verify but good luck.

  • to place scrollArea the target position,

    • Manually call SetGeometry, or
    • Place a QScrollArea in ui form, (suggested if it's static), or
    • Place a widget in your target position, and set QScrollArea's parent to it, and add QScrollArea to its layout, and Set QScrollArea to be expanding.
  • manually create a QWidget innerWidget and assign it to scrollArea via QScrollArea::setWidget(*QWidget), try different size policy to innerWidget, such as "Preferred".

Also be aware of Qt's reference mentioned : void QScrollArea::setWidget ( QWidget * widget ) Sets the scroll area's widget. .... Note that You must add the layout of widget before you call this function; if you add it later, the widget will not be visible - regardless of when you show() the scroll area. In this case, you can also not show() the widget later.

Above list solutions, below are reasons to the problems you mentioned:

  • scrollArea->setWidget(ui->innerWidget); Setting a widget to ScrollArea will change the parenting and layouting of ui->innerWidget, so the geometry values written in ui form (in Qt Creater) will no longer take effect, this is the reason of innerWidget out of place. ui->innerWidget is no longer a child of outerWidget, it's geometry will follow its new parent (but not scrollArea, there's some tricky layouting inside QScrollArea". To be clear, innerWidget is not helpful to locate scrollArea in such scenario.

  • In your first clip of code, widget 'scrollArea' is created with parent outerWidget, again no size policy or layout or geometry is specified, so scrollArea will by default be placed at the left top corner of the parent "outerWidget". To place scrollArea to your target geometry, you can " set geometry manually " or " assign innerWidget as scrollArea's parent and expand scrollArea". Obviously the latter method cannot assign ui->innerWiget to scrollArea->setWidget().

  • scrollArea->setWidgetResizable(true); makes the scrollArea "shrink" at left top corner of outerWidget. This is because, QScrollArea does not increase along with it's contents, it can scroll to display all of it contents so the required size of QScrollArea can be as small as possible. Once the 'Resizable' property is set to "true", QScrollArea decides to shrink to its minimum necessary size, thus the size to display its scroll bar and scroll buttons....

Martian Puss
  • 710
  • 2
  • 7
  • 16
  • Thanks a lot, great answer! I had the impression that scrollArea will get the geometry of innerWidget and obviously I was wrong. – Vasilis Feb 25 '14 at 06:02
  • Fantastic answer. I had a form layout that I was directly adding as the layout of my scroll area, but there were so many rows, it would shrink to the point everything was invisible. Creating a generic QWidget first, then adding my layout to that, then adding that as the scroll area's widget worked like a charm! – Bal Apr 29 '16 at 15:10