C++ 调用setItemWidget时崩溃
我正在使用QTreeWidget并在QTreeWidget中为QTreeWidgetItem设置一个小部件。它工作正常,但当我第二次这样做时,应用程序崩溃了C++ 调用setItemWidget时崩溃,c++,qt,qtreewidget,qtreewidgetitem,C++,Qt,Qtreewidget,Qtreewidgetitem,我正在使用QTreeWidget并在QTreeWidget中为QTreeWidgetItem设置一个小部件。它工作正常,但当我第二次这样做时,应用程序崩溃了 QTreeWidget* treewidget = new QTreeWidget(); QTreeWidgetItem* item0 = new QTreeWidgetItem((QTreeWidget*)0, QStringList(QString("item0"))); treewidget->insertTopLevelIte
QTreeWidget* treewidget = new QTreeWidget();
QTreeWidgetItem* item0 = new QTreeWidgetItem((QTreeWidget*)0, QStringList(QString("item0")));
treewidget->insertTopLevelItem(0,item0);
QSlider* slider0 = new QSlider();
treewidget->setItemWidget(item0, 0, slider0);
treewidget->setItemWidget(item0, 0, slider0); // Intentionally added to simulate the issue
下面的工作正常
QTreeWidget* treewidget = new QTreeWidget();
QTreeWidgetItem* item0 = new QTreeWidgetItem((QTreeWidget*)0, QStringList(QString("item0")));
treewidget->insertTopLevelItem(0,item0);
QSlider* slider0 = new QSlider();
treewidget->setItemWidget(item0, 0, slider0);
但是如果我再次添加最后一行,它在运行应用程序时会崩溃
下面的机器正在崩溃
QTreeWidget* treewidget = new QTreeWidget();
QTreeWidgetItem* item0 = new QTreeWidgetItem((QTreeWidget*)0, QStringList(QString("item0")));
treewidget->insertTopLevelItem(0,item0);
QSlider* slider0 = new QSlider();
treewidget->setItemWidget(item0, 0, slider0);
treewidget->setItemWidget(item0, 0, slider0); // Intentionally added to simulate the issue
上面是一个显示问题的示例,但是在我的应用程序中,基于一些事件,我删除了树小部件项,然后添加它。当我设置项目小部件时(稍后添加项目之后),我得到了崩溃
我不明白为什么。有什么想法吗?仅供参考,我使用的是Qt 5.3.2 MSVC 2010,32位。您必须在
QTreeWidgetItem
的构造函数中设置正确的parent
。试试这个:
QTreeWidgetItem* item0 = new QTreeWidgetItem(treewidget);
调用setItemWidget()
后,了解谁是slider0
的所有者也很重要:所有者是您的表,因此1)您不需要删除此对象;2) 如果再次为同一单元格调用setItemWidget
,该对象将被删除。因此,双重调用treewidget->setItemWidget(item0,0,slider0)代码>看起来很奇怪(第二次将删除的对象设置到该单元格中时)
我看一下Qt代码(4.x):
和qabstractemview::setIndexWidget
:
void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget)
{
Q_D(QAbstractItemView);
if (!d->isIndexValid(index))
return;
if (QWidget *oldWidget = indexWidget(index)) {
d->persistent.remove(oldWidget);
d->removeEditor(oldWidget);
oldWidget->deleteLater();
}
所以如果你添加了两次slider0,那么在第一次调用时它被添加了,
几秒钟后调用Qt调用它deleteLater
,然后添加它,
你确定这就是你想要的吗?@Sankar,好的,但无论如何设置正确的父项都很重要。我已经扩展了我的答案(请参阅user1034749答案中的详细信息)@llya,实际上我正在尝试实现一个包含树小部件的属性窗口。每个树小部件项都包含一个小部件(使用setItemWidget()设置)。属性窗口显示我正在选择的对象的属性。假设树小部件显示对象A的属性,我选择对象B,当我再次选择对象A时,我删除树小部件中的项目(实际上属于对象B)并再次添加对象A项目。当我这样做时,它没有我最初设置的项目小部件。所以我再次设置了item小部件,这导致了崩溃。“实际上属于对象B”是什么意思?如果它的意思是“实际对应于”,则可以(即,如果您在调用setItemWidget
之前创建了新的小部件)。但是,如果您使用对象(对象B的一部分)上的指针作为setItemWidget
的参数,这是错误的,因为在这种情况下,您将失去所有权(这就是崩溃的原因)。不,我没有使用对象B的指针作为“setItemWidget”的参数。我两次使用同一个小部件作为“setItemWidget”的参数。正如您所说,当我第二次调用“setItemWidget”时,它被删除。这可能是坠机的原因之一。无论如何,我必须为我的用例寻找不同的方法。谢谢
void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget)
{
Q_D(QAbstractItemView);
if (!d->isIndexValid(index))
return;
if (QWidget *oldWidget = indexWidget(index)) {
d->persistent.remove(oldWidget);
d->removeEditor(oldWidget);
oldWidget->deleteLater();
}