This doesn\'t seem easy. Basically, I add QPushButton
s through a function to a layout, and when the function executes, I want to clear the layout first (removi
If you don't do anything funny when adding widgets to layouts and layouts to other layouts they should all be reparented upon addition to their parent widget. All QObject
s have a deleteLater()
slot which will cause the QObject
to be deleted as soon as control is returned to the event loop. Widgets deleted in this Manor also delete their children. Therefore you simply need to call deleteLater()
on the highest item in the tree.
in hpp
QScrollArea * Scroll;
in cpp
void ClearAndLoad(){
Scroll->widget()->deleteLater();
auto newLayout = new QVBoxLayout;
//add buttons to new layout
auto widget = new QWidget;
widget->setLayout(newLayout);
Scroll->setWidget(widget);
}
also note that in your example the _layout
is a local variable and not the same thing as the _layout
in the header file (remove the QVBoxLayout*
part). Also note that names beginning with _
are reserved for standard library implementers. I use trailing _
as in var_
to show a local variable, there are many tastes but preceding _
and __
are technically reserved.
This code deletes all its children. So everything inside the layout 'disappears'.
qDeleteAll(yourWidget->findChildren<QWidget *>(QString(), Qt::FindDirectChildrenOnly));
This deletes all direct widgets of the widget yourWidget
. Using Qt::FindDirectChildrenOnly
is essential as it prevents the deletion of widgets that are children of widgets that are also in the list and probably already deleted by the loop inside qDeleteAll
.
Here is the description of qDeleteAll
:
void qDeleteAll(ForwardIterator begin, ForwardIterator end)
Deletes all the items in the range [begin, end] using the C++ delete > operator. The item type must be a pointer type (for example, QWidget *).
Note that qDeleteAll
needs to be called with a container from that widget (not the layout). And note that qDeleteAll
does NOT delete yourWidget
- just its children.
only works for my buttonlist, if the widgets themeselves are deleted, too. otherwise the old buttons are still visible:
QLayoutItem* child;
while ((child = pclLayout->takeAt(0)) != 0)
{
if (child->widget() != NULL)
{
delete (child->widget());
}
delete child;
}
I had a similar case where I have a QVBoxLayout
containing dynamically created QHBoxLayout
objects containing a number of QWidget
instances. For some reason I couldn't get rid of the widgets either by deleting neither the top level QVBoxLayout or the individual QHBoxLayouts. The only solution I got to work was by going through the hierarchy and removing and deleting everything specifically:
while(!vbox->isEmpty()) {
QLayout *hb = vbox->takeAt(0)->layout();
while(!hb->isEmpty()) {
QWidget *w = hb->takeAt(0)->widget();
delete w;
}
delete hb;
}
I have a possible solution for this problem (see Qt - Clear all widgets from inside a QWidget's layout). Delete all widgets and layouts in two seperate steps.
Step 1: Delete all widgets
QList< QWidget* > children;
do
{
children = MYTOPWIDGET->findChildren< QWidget* >();
if ( children.count() == 0 )
break;
delete children.at( 0 );
}
while ( true );
Step 2: Delete all layouts
if ( MYTOPWIDGET->layout() )
{
QLayoutItem* p_item;
while ( ( p_item = MYTOPWIDGET->layout()->takeAt( 0 ) ) != nullptr )
delete p_item;
delete MYTOPWIDGET->layout();
}
After step 2 your MYTOPWIDGET should be clean.
You do not write about going the other way, but you could also just use a QStackedWidget
and add two views to this, one for each arrangement of buttons that you need. Flipping between the two of them is a non issue then and a lot less risk than juggling various instances of dynamically created buttons