调用setItemWidget时崩溃

时间:2015-11-10 09:32:54

标签: c++ qt qtreewidget qtreewidgetitem

我正在使用QTreeWidget并在QTreeWidget中为QTreeWidgetItem设置一个小部件。它工作正常但是当我第二次这样做时,应用程序崩溃了。

以下工作正常。

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位。

2 个答案:

答案 0 :(得分:1)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.app.path" >    

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
 <!-- ... other permissions -->

<permission
    android:name="my.app.path.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />

<uses-permission android:name="my.app.path.permission.C2D_MESSAGE" />

<application
    ...>
     <!-- ... activites... -->

    <receiver
        android:name="com.google.android.gms.gcm.GcmReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <category android:name="my.app.path" />
        </intent-filter>
    </receiver>      

    <service
        android:name=".MyGcmListener"
        android:exported="false"
        android:enabled="true" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
    </service>

</application>

</manifest>

我看一下Qt代码(4.x):

treewidget->setItemWidget(item0, 0, slider0);
treewidget->setItemWidget(item0, 0, slider0);// Intentionally added to simulate the issue

void QTreeWidget::setItemWidget(QTreeWidgetItem *item, int column, QWidget *widget) { Q_D(QTreeWidget); QAbstractItemView::setIndexWidget(d->index(item, column), widget); }

QAbstractItemView::setIndexWidget

所以如果你添加了两次slider0,那么在第一次调用时它会被添加, 在秒钟调用Qt调用它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(); } ,然后添加它, 确定这是你想要的吗?

答案 1 :(得分:0)

您必须在parent的构造函数中设置正确的QTreeWidgetItem。试试这个:

QTreeWidgetItem* item0 = new QTreeWidgetItem(treewidget);

在调用slider0之后,了解谁是setItemWidget()的所有者也很重要:所有者是您的表,因此1)您不需要删除此对象; 2)如果再次为同一个单元调用setItemWidget,将删除该对象。所以,treewidget->setItemWidget(item0, 0, slider0);的双重调用似乎很奇怪(第二次将删除的对象设置到该单元格中)。