PDA

View Full Version : QScrollArea: clearing the layout of the inner widget



mattc
2nd August 2009, 19:46
Hello,
I created a scroll area and called setWidget() to set the "inner" widget. The inner widget has a layout that I want to clear from time to time. In the documentation for QLayout::takeAt() I found this:

http://doc.trolltech.com/4.5/qlayout.html#takeAt

Unfortunately, it does not work (it looks like a redraw problem). What works is keeping a separate list of added widgets, and deleting them manually. I can't understand what's going on. I'm posting a complete test class showing the problem:


#include <QWidget>
#include <QVBoxLayout>
#include <QPushButton>
#include <QScrollArea>
#include <QLabel>
#include <QList>

class ScrollAreaTest : public QWidget
{
Q_OBJECT

public:
ScrollAreaTest(QWidget* parent = 0):
QWidget(parent)
{
// buttons
QPushButton* btnAdd = new QPushButton("Add label");
connect(btnAdd, SIGNAL(clicked()), this, SLOT(onBtnAdd()));

QPushButton* btnClear1 = new QPushButton("Clear Layout (mode 1)");
connect(btnClear1, SIGNAL(clicked()), this, SLOT(onBtnClear1()));

QPushButton* btnClear2 = new QPushButton("Clear Layout (mode 2)");
connect(btnClear2, SIGNAL(clicked()), this, SLOT(onBtnClear2()));

// scroll area
QScrollArea* myScrollArea = new QScrollArea();
myScrollArea->setWidgetResizable(true);
myScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOf f);
myScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);

// scroll area "inner" widget
QWidget* innerWidget = new QWidget();
innerWidgetLayout = new QVBoxLayout();
innerWidget->setLayout(innerWidgetLayout);

// set scroll area inner widget
myScrollArea->setWidget(innerWidget);

// main layout
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(btnAdd);
layout->addWidget(btnClear1);
layout->addWidget(btnClear2);
layout->addWidget(myScrollArea);
setLayout(layout);
}

private:
QVBoxLayout* innerWidgetLayout;
QList<QLabel*> addedLabels;

private slots:

void onBtnAdd()
{
QLabel* l = new QLabel("Hello there!");
innerWidgetLayout->addWidget(l);

addedLabels.push_back(l); // I'm keeping a list of added labels (see onBtnClear2)
}

void onBtnClear1() // this is from the docs and doesn't work
{
QLayoutItem *child;

while ((child = innerWidgetLayout->takeAt(0)) != 0)
delete child;

/*
innerWidgetLayout->activate();
innerWidgetLayout->update();
update();
*/
}

void onBtnClear2() // this works
{
for (QList<QLabel*>::iterator it = addedLabels.begin(); it != addedLabels.end(); ++it)
delete *it;

addedLabels.clear();
}
};

Thank you

mattc
3rd August 2009, 08:09
I solved changing


QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
...
delete child;
}

to


QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
...
delete child->widget(); // delete Layout Item's underlying widget
}