EDIT:
After some more testing (without looking at the source code, but suspecting that it must be safe to delete button, else things would be brittle), I've implemented removeButtons as follows:
void ButtonWidget::deleteButtons()
{
while(myLayout->count())
{
delete myLayout->itemAt(0)->widget();
}
}
This works, and it proves that deleting a widget also removes the widget from it's parent, and layouts associated with the parent (by slots hooked up to when a child widget is deleted). The above code confirms this, as count(), which refers to number of layout items, decrease to zero (and those layout items are managed by the Layout). takeAt(x) is never called, and doesn't need to be - simply delete the widgets (buttons). Wholla!
ORIGINAL ANSWER
As mentioned in my other post, you only need to delete the buttons (it is removed from its parent automatically). However, if a widget was added to a layout, the parent of that layout becomes the parent of the widget, and an associated QLayoutItem is created that is managed by the layout itself. To the delete the buttons, the safest way is to take all the layout items (ownership the taker's responsibility), delete each items associated widget, and the delete each item. I'll try and find relevant references apart from the sources...
The following code works:
//ButtonWidget.h
#include <QWidget>
#include <QScrollArea>
#include <QHBoxLayout>
class ButtonWidget : public QScrollArea
{
Q_OBJECT
public:
ButtonWidget(QWidget *parent = 0);
~ButtonWidget();
void addButtons();
void deleteButtons();
private:
QHBoxLayout* myLayout;
};
//ButtonWidget.cpp
#include "ButtonWidget.h"
#include <QGridLayout>
#include <QPushButton>
#include <QLayoutItem>
ButtonWidget::ButtonWidget(QWidget * parent) :
QScrollArea(parent),
myLayout(new QHBoxLayout(this))
{
}
ButtonWidget::~ButtonWidget()
{
}
void ButtonWidget::addButtons()
{
QStringList texts{"1\nok", "2\nok", "3\nok", "4\nok", "5\nok", "6\nok"};
for(int i = 0; i < texts.size(); i++)
{
myLayout->addWidget(new QPushButton(texts[i]));
}
}
void ButtonWidget::deleteButtons()
{
QLayoutItem * child;
while((child = myLayout->takeAt(0)) != 0)
{
delete child->widget();
delete child;
}
}
#include "ButtonWidget.h"
#include <QApplication>
#include <QScrollArea>
#include <QPushButton>
#include <QGridLayout>
#include <QHBoxLayout>
#include <memory>
std::unique_ptr<QScrollArea> makeArea()
{
std::unique_ptr<QScrollArea> area(new QScrollArea);
auto layout = new QGridLayout(area.get());
auto addButton = new QPushButton("Add");
auto removeButton = new QPushButton("Remove");
layout->addWidget(addButton, 0, 0);
layout->addWidget(removeButton, 0, 1);
auto btnWidget = new ButtonWidget;
layout->addWidget(btnWidget,1,0,1,2);
QObject::connect(addButton, &QPushButton::clicked, [=]()
{
btnWidget->addButtons();
});
QObject::connect(removeButton, &QPushButton::clicked, [=]()
{
btnWidget->deleteButtons();
});
return move(area);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
auto area = makeArea();
area->show();
return a.exec();
}
You need to enable c++11 in your config (.pro) to get the lambdas working.
CONFIG += c++11
I've used QHBoxLayout for your buttons, as it better models what you want. Although strictly not necessary, I'm returning unique_ptr from the makeArea in main, as it has not parent, I'm not sure whether it gets some parent because it is the first widget created, but unique_ptr shows intent.
NOTE:
Apparently the layout item is not the parent of the widget, but the widget associated with the layout itself is the parent of widgets belonging to its layout item.