Объяснение
Вы не должны вручную удалять виджет, добавленный к QTreeWidget , поскольку он автоматически удаляется либо
- уничтожение виджета его родительского дерева
Это прямое следствие механизма Qt parent-child.
- вызов
QTreeWidget::removeItemWidget
в любое время деревавиджет все еще живет.
Этот не так очевиден, так как документация просто говорит:
Удаляет виджет, установленный в данном элементе вданный столбец.
Однако, глядя на исходный код , становится довольно ясно, что на самом деле происходит, то есть
QTreeWidget::removeItemWidget
звонки QTreeWidget::setItemWidget
с указателем null
(без виджета)
inline void QTreeWidget::removeItemWidget(QTreeWidgetItem *item, int column)
{ setItemWidget(item, column, nullptr); }
QTreeWidget::setItemWidget
по очереди звонки QAbstractItemView::setIndexWidget
void QTreeWidget::setItemWidget(QTreeWidgetItem *item, int column, QWidget *widget)
{
Q_D(QTreeWidget);
QAbstractItemView::setIndexWidget(d->index(item, column), widget);
}
Наконец QAbstractItemView::setIndexWidget
проверяет, есть ли уже виджет с этим индексом, и, если он есть, вызывает его deleteLater
метод
if (QWidget *oldWidget = indexWidget(index)) {
d->persistent.remove(oldWidget);
d->removeEditor(oldWidget);
oldWidget->removeEventFilter(this);
oldWidget->deleteLater();
}
Проще говоря (и это должно быть ясно указано в документации обоих методов QTreeWidget
), любой вызов QTreeWidget::setItemWidget
или QTreeWidget::removeItemWidget
удаляет виджет (если есть) уженабор для элемента .
Пример
Вот простой пример, который я подготовил для вас, чтобы продемонстрировать описанное поведение:
#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();
}
Результат
Описанные способы уничтожения виджета можно протестировать с помощью приложения
![Application window with a button and a combo box in a tree widget](https://i.stack.imgur.com/WSpSO.png)
- Простое закрытие окна разрушает виджет деревавместе со своим дочерним комбинированным списком, следовательно, испускается разрушенный сигнал комбинированного блока, и лямбда печатает
The combo box is gone.
- После нажатия кнопки лямбда-функция, связанная с егоВызывается сигнал
clicked
, который удаляет поле со списком из виджета дерева. Поскольку поле со списком также удаляется (автоматически), вызывается лямбда из второго оператора connect
, который также печатает
The combo box is gone.