Johannes
Johannes

Reputation: 3099

Letting QWidget and QVBoxLayout automatically resize if child resizes (Qt4)

I have the following minimal example code given.

main.cpp:

#include <QApplication>
#include "qt.h"

int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    MyDialog mainWin;
    mainWin.show();
    return app.exec();
}

qt.cpp:

#include <QLabel>
#include "qt.h"

void MyDialog::setupUi()
{
    setCentralWidget(new QWidget);
    mainLayout = new QVBoxLayout( centralWidget() );
    centralWidget()->setLayout(mainLayout);

    // show the add new effect channel button
    QPushButton* newKnobBtn = new QPushButton("new", this );
    connect( newKnobBtn, SIGNAL(clicked()), this, SLOT(addNewKnob()));
    mainLayout->addWidget( newKnobBtn, 0, Qt::AlignRight );

    containerWidget = new QWidget(this);
    scrollArea = new QScrollArea(containerWidget);
    mainLayout->addWidget(containerWidget);

    scrollLayout = new QVBoxLayout(scrollArea);
    scrollArea->setLayout(scrollLayout);

    /*
    QSizePolicy pol;
    pol.setVerticalPolicy(QSizePolicy::Expanding);
    setSizePolicy(pol);
    */

    addNewKnob(); // to fit size initially
}

void MyDialog::addNewKnob()
{
    scrollLayout->addWidget(new QLabel("Hello World", this));
    /*
    containerWidget->adjustSize();
    adjustSize();
    */
}

qt.h:

#include <QMainWindow>
#include <QVBoxLayout>
#include <QScrollArea>
#include <QPushButton>

class MyDialog : public QMainWindow
{
    Q_OBJECT
private slots:
    void addNewKnob();
private:
    void setupUi();
    QVBoxLayout* mainLayout;
    QScrollArea* scrollArea;
    QVBoxLayout* scrollLayout;
    QWidget* containerWidget;
public:
    MyDialog( ) { setupUi(); }
};

Compiling: Put all in one directory, type

qmake -project && qmake && make

I have the adjustSize() solution from here, but it does not work: (link). Everything I commented out was things I tried but did not help.

How do I make containerWidget and scrollLayout grow correctly, when a new Label is being added to scrollLayout?

Upvotes: 1

Views: 2799

Answers (2)

Jeremy Friesner
Jeremy Friesner

Reputation: 73081

Here's a simplified version that works for me:

qt.cpp:

#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include "qt.h"

MyDialog::MyDialog()
{
    QWidget * mainWidget = new QWidget;
    QBoxLayout * mainLayout = new QVBoxLayout(mainWidget);
    setCentralWidget(mainWidget);

    // show the add new effect channel button
    QPushButton* newKnobBtn = new QPushButton("new");
    connect( newKnobBtn, SIGNAL(clicked()), this, SLOT(addNewKnob()));
    mainLayout->addWidget( newKnobBtn, 0, Qt::AlignRight );

    QScrollArea * scrollArea = new QScrollArea;
    scrollArea->setWidgetResizable(true);
    mainLayout->addWidget(scrollArea);

    QWidget * labelsWidget = new QWidget;
    labelsLayout = new QVBoxLayout(labelsWidget);
    scrollArea->setWidget(labelsWidget);

    addNewKnob(); // to fit size initially
}

void MyDialog::addNewKnob()
{
    labelsLayout->addWidget(new QLabel("Hello World"));
}

qt.h:

#include <QMainWindow>
#include <QBoxLayout>

class MyDialog : public QMainWindow
{
    Q_OBJECT

public:
    MyDialog( );

private slots:
    void addNewKnob();

private:
    QBoxLayout * labelsLayout;
};

Upvotes: 2

Pavel Strakhov
Pavel Strakhov

Reputation: 40502

You have containerWidget that contain only one QScrollArea. I don't know why do you need this. But if you need this for some reason, you need to add a layout to this widget in order to make layouts work. Also do not create a layout for QScrollArea. It already have internally implemented layout. You should add scrollLayout to the scroll area's viewport() widget instead.

When you construct a layout and pass a widget to its constructor, the layout is automatically assigned to the passed widget. You should not call setLayout after that. This action will take no effect and produce console warning.

Upvotes: 0

Related Questions