How to make a QScrollArea resize to fit its contents?
-
How i could make a
QScrollArea
stick on the top and grow according to the widgets added to it?When I add the
QScrollArea
to the layout asvlayout->addWidget(scrollArea, 0, Qt::AlignTop);
it doesn't obey the
Qt::AlignTop
flag and is floating on the middle:class Widget : public QWidget // source: Qt6 { Q_OBJECT public: Widget() : QWidget(nullptr) { QVBoxLayout* vlayout = new QVBoxLayout(this); QScrollArea* scrollArea = new ScrollArea(this); QWidget* scrollAreaWidget = new QWidget(scrollArea); QVBoxLayout* scrollAreaLayout = new QVBoxLayout(scrollAreaWidget); scrollAreaLayout->setContentsMargins(0, 0, 0, 0); scrollAreaLayout->setSizeConstraint(QLayout::SetFixedSize); scrollAreaWidget->setLayout(scrollAreaLayout); scrollArea->setWidget(scrollAreaWidget); scrollArea->setWidgetResizable(true); scrollArea->setAlignment(Qt::AlignTop); scrollArea->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); //scrollArea->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); QPushButton* add = new QPushButton("add", this); connect(add, &QPushButton::clicked, [=] { QWidget* widget = new QWidget; QHBoxLayout* hlayout = new QHBoxLayout(widget); hlayout->setContentsMargins(0, 0, 0, 0); QPushButton* button = new QPushButton("button_" + QString::number(scrollAreaLayout->count()), this); button->setFixedWidth(300); QPushButton* remove = new QPushButton("remove", this); hlayout->addWidget(button); hlayout->addWidget(remove); connect(remove, &QPushButton::clicked, [=]{ widget->deleteLater(); }); scrollAreaLayout->addWidget(widget, 0, Qt::AlignTop); }); vlayout->addWidget(add, 0, Qt::AlignTop); //vlayout->addWidget(scrollArea); vlayout->addWidget(scrollArea, 0, Qt::AlignTop); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget widget; widget.show(); }
When i add it to the layout as
vlayout->addWidget(scrollArea);
it grows to the entire layout height:I have tried all size policies
scrollArea->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
and also:scrollArea->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
On the documentation it says:
QAbstractScrollArea::AdjustToContents
The scroll area will always adjust to the viewportWhy is it not adjusting? I'm doing something wrong?
What i'm trying to achieve is to have it on the top and make it grow according to the widgets added to it.It would look like this:
Then it would continue growing for each widget added until there's no more space on the parent layout, and at this point it would then display the
QScrollBars
. -
Hi, it look like you have too many QVBoxLayouts up and running, and probably you're doing the setAlignment(Qt::AlignTop); on the wrong one (the lowest in the hierarchy).
Try doing the allignment setting on the top/outer QVBoxLayout, say like this:
... Widget() : QWidget(nullptr) { QVBoxLayout* vlayout = new QVBoxLayout(this); vlayout->setAlignment(Qt::AlignTop); ...
-
Now the QScrollArea stick on top but if i set:
scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
It doesn't grow when new widgets are added to it, and if i set:
scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
It grows to the entire layout height which is not what im trying to achieve.
-
@Laila
I don't think it is possible.However your code is confused.
Widget() : QWidget(nullptr) { QVBoxLayout* vlayout = new QVBoxLayout(this); QPushButton* add = new QPushButton("add"); QScrollArea* scrollArea = new QScrollArea; vlayout->addWidget(add); vlayout->addWidget(scrollArea); QWidget* scrollAreaWidget = new QWidget; QVBoxLayout* scrollAreaLayout = new QVBoxLayout(scrollAreaWidget); scrollAreaLayout->setContentsMargins(0, 0, 0, 0); //scrollAreaLayout->setSizeConstraint(QLayout::SetFixedSize); scrollAreaWidget->setLayout(scrollAreaLayout); scrollArea->setWidget(scrollAreaWidget); scrollArea->setWidgetResizable(true); scrollArea->setAlignment(Qt::AlignTop); //scrollArea->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); //scrollArea->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); connect(add, &QPushButton::clicked, [=] { QWidget* widget = new QWidget; QHBoxLayout* hlayout = new QHBoxLayout(widget); hlayout->setContentsMargins(0, 0, 0, 0); QPushButton* button = new QPushButton("button_" + QString::number(scrollAreaLayout->count()), this); button->setFixedWidth(300); QPushButton* remove = new QPushButton("remove", this); hlayout->addWidget(button); hlayout->addWidget(remove); connect(remove, &QPushButton::clicked, [=]{ widget->deleteLater(); }); scrollAreaLayout->addWidget(widget, 0, Qt::AlignTop); }); // vlayout->addWidget(add, 0, Qt::AlignTop); // //vlayout->addWidget(scrollArea); // vlayout->addWidget(scrollArea, 0, Qt::AlignTop); }
-
QAbstractScrollArea::AdjustToContents() I think works fine, the problem I think is that nothing currently resizes the scrollArea (inside the QVBoxLayout). Once it resized the QAbstractScrollArea::AdjustToContents() will work.
The horizontal resizing is done courtesy of the QVBoxLayout so you only need to take care of the vertical resizing, once simple (stupid :-) would be to do the resizing via the resizeEvent, say you add this code after Widget's constructor:
... void resizeEvent(QResizeEvent* event) { scrollArea->setMinimumHeight(height() - 60); // 60 or maybe something bigger to avoid endless resizing }
Also you need to move the variable declaration for the scrollArea outside of the constructor (so it can be reached from the resize event) say change like this:
public: QScrollArea* scrollArea; Widget() : QWidget(nullptr) { QVBoxLayout* vlayout = new QVBoxLayout(this); scrollArea = new ScrollArea(this); QWidget* scrollAreaWidget = new QWidget(scrollArea); ...