Explaination
You should not manually delete a widget, added to a QTreeWidget, since it is automatically deleted either by
- destructing its parent tree widget
This is a direct consequence of the Qt's parent-child mechanism.
- calling
QTreeWidget::removeItemWidget
anytime the tree widget still lives.
This one is not so obvious, since the documentation simply sais:
Removes the widget set in the given item in the given column.
However, looking at the source code it becomes pretty clear what is indeed happening, i.e.
QTreeWidget::removeItemWidget
calls QTreeWidget::setItemWidget
with a null
pointer (no widget)
inline void QTreeWidget::removeItemWidget(QTreeWidgetItem *item, int column)
{ setItemWidget(item, column, nullptr); }
QTreeWidget::setItemWidget
in turn calls QAbstractItemView::setIndexWidget
void QTreeWidget::setItemWidget(QTreeWidgetItem *item, int column, QWidget *widget)
{
Q_D(QTreeWidget);
QAbstractItemView::setIndexWidget(d->index(item, column), widget);
}
Finally QAbstractItemView::setIndexWidget
checks if there is already a widget at this index, and if there is one, calls its deleteLater
method
if (QWidget *oldWidget = indexWidget(index)) {
d->persistent.remove(oldWidget);
d->removeEditor(oldWidget);
oldWidget->removeEventFilter(this);
oldWidget->deleteLater();
}
Simply put (and this should be made clear in the documentation of both methods of QTreeWidget
), any call to QTreeWidget::setItemWidget
or QTreeWidget::removeItemWidget
deletes the widget (if any) already set for the item.
Example
Here is a simple example I have prepared for you in order to demonstrate the described behaviour:
#include <QApplication>
#include <QBoxLayout>
#include <QTreeWidget>
#include <QComboBox>
#include <QPushButton>
struct MainWindow : public QWidget
{
MainWindow(QWidget *parent = nullptr) : QWidget(parent) {
auto *l = new QVBoxLayout(this);
auto *treeWidget = new QTreeWidget(this);
auto *item = new QTreeWidgetItem(treeWidget);
auto *button = new QPushButton(tr("Remove combo box"), this);
auto *comboBox = new QComboBox();
comboBox->addItems(QStringList() << "Bird" << "Fish" << "Ape");
treeWidget->setItemWidget(item, 0, comboBox);
l->addWidget(button);
l->addWidget(treeWidget);
connect(comboBox, &QComboBox::destroyed, [](){
qDebug("The combo box is gone.");
});
connect(button, &QPushButton::clicked, [treeWidget, item](){
treeWidget->removeItemWidget(item, 0);
});
resize(400, 300);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Result
The described ways of destroyng the widget could be tested with the application

- Simply closing the window destroys the tree widget together with its child combo box, hence the combo box's destroyed signal is emitted and the lambda prints
The combo box is gone.
- After pressing the button the lambda function connected to its
clicked
signal is called, which removes the combo box from the tree widget. Because the combo box is deleted (automatically) as well, the lambda from the second connect
statement is called, which also prints
The combo box is gone.