我在表格视图的每一行的最后一列中都有一个删除按钮(QPushButton)。我正在创建这些按钮并直接在视图中设置它们。由于我已经动态分配了内存,我希望释放这个内存,但我没有在任何地方存储这些按钮的指针,所以我试图在清理和删除它时获取小部件。
SDelegate* myDelegate;
myDelegate = new SDelegate();
STableModel* model = new STableModel(1, 7, this);
myWindow->tableView->setModel(model);
myWindow->tableView->setItemDelegate(myDelegate);
for(int i = 0; i < no_of_rows; ++i) {
QPushButton* deleteButton = new QPushButton();
myWindow->tableView->setIndexWidget(model->index(i, 6), deleteButton);
}
exec();
// Cleanup
for(int i = 0; i < no_of_rows; ++i) {
// code works fine on removing this particular section
QWidget* widget = myWindow->tableView->indexWidget(model->index(i, 6));
if (widget)
delete widget;
}
delete model;
delete myDelegate;
我在qt5cored.dll(未处理的异常)中崩溃,应用程序在qcoreapplication.h中崩溃,代码如下:
#ifndef QT_NO_QOBJECT
inline bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
{ if (event) event->spont = false; return self ? self->notifyInternal(receiver, event) : false; }
在调试时,删除这些小部件没有问题,但代码在其他时间点崩溃。我正在使用QTableView和继承QAbstractTableModel的模型的自定义类。
答案 0 :(得分:1)
有一个Qt错误,表现如下:如果有任何索引小部件,并且您在视图上调用setModel(nullptr)
,它将在visualRow != -1
qtableview.cpp:1625
中的断言中崩溃(在Qt 5.6.0中)。据推测,当以某种其他方式移除模型时,可能会触发此错误。
但是我不能通过仅仅破坏模型实例来重现它。所以我怀疑它在这里是相关的,除非你得到相同的断言失败。
鉴于您的代码风格,您更有可能在其他地方出现内存错误。如果您认为上面的代码崩溃了,您应该有一个自包含的测试用例来演示崩溃。你的模特或代表应该受到指责吗?使用没有委托会崩溃吗?使用库存模型会崩溃吗?
你的代码摘录似乎很好,如果大多数是不必要的。您可以在本地分配委托和模型。按钮由视图拥有:只要按钮需要消失,例如当模型更改行数或消失时,它们将被适当删除。所以你不必自己删除它们,这是安全的,但完全没必要。
这是一个示例,演示了在所有情况下,当模型被破坏或视图被破坏时,按钮将被释放,以先到者为准。在Qt中跟踪对象的生命周期非常简单:保留一组对象,并使用附加到对象的destroyed
信号的仿函数将它们从集合中移除。在Qt 4中,你将使用带插槽的辅助类。
// https://github.com/KubaO/stackoverflown/tree/master/questions/model-indexwidget-del-38796375
#include <QtWidgets>
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QSet<QObject*> live;
{
QDialog dialog;
QVBoxLayout layout{&dialog};
QTableView view;
QPushButton clear{"Clear"};
layout.addWidget(&view);
layout.addWidget(&clear);
QScopedPointer<QStringListModel> model{new QStringListModel{&dialog}};
model->setStringList(QStringList{"a", "b", "c"});
view.setModel(model.data());
for (int i = 0; i < model->rowCount(); ++i) {
auto deleteButton = new QPushButton;
view.setIndexWidget(model->index(i), deleteButton);
live.insert(deleteButton);
QObject::connect(deleteButton, &QObject::destroyed, [&](QObject* obj) {
live.remove(obj); });
}
QObject::connect(&clear, &QPushButton::clicked, [&]{ model.reset(); });
dialog.exec();
Q_ASSERT(model || live.isEmpty());
}
Q_ASSERT(live.isEmpty());
}
答案 1 :(得分:-1)
查看QObject::deleteLater(),它通常有助于解决有关删除QObjects / QWidgets的问题。