从QTableView中删除窗口小部件 [英] Deleting a widget from QTableView

查看:585
本文介绍了从QTableView中删除窗口小部件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在表视图的每一行的最后一列有一个删除按钮(QPushButton)。我创建这些按钮并直接设置它们在视图中。由于我已经动态分配内存,我希望释放这个内存,但我没有存储这些按钮的指针任何地方,所以我想在清理和删除它们时获取该小部件。

I have a delete button(QPushButton) in the last column of each row of my table view. I am creating these push buttons and directly setting them in view. Since I have allocated memory dynamically I wish to free this memory but I haven't stored pointers of these buttons anywhere so I am trying to obtain the widget at the time of clean up and deleting them.

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在以下代码:

I am getting a crash in qt5cored.dll (Unhandled exception) and application is crashing in qcoreapplication.h at the following code:

#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的模型。

While debugging there is no issue in deleting these widgets but code crashes afterwards at some other point. I am using QTableView and custom class for model which has inherited QAbstractTableModel.

推荐答案

有一个Qt错误,如下:是任何索引小部件,并且您在视图上调用 setModel(nullptr),它将在 visualRow!= -1 qtableview.cpp:1625 (在Qt 5.6.0)。假设当模型以某种其他方式被移除时,这个错误可能被触发。

There's a Qt bug that manifests as follow: if there are any index widgets, and you invoke setModel(nullptr) on the view, it'll crash in an assertion on visualRow != -1 in qtableview.cpp:1625 (in Qt 5.6.0). Presumably this bug could be triggered when the model is being removed in some other fashion too.

但是我不能通过破坏模型实例来重现它。所以我怀疑这里是相关的,除非你得到相同的断言失败。

But I can't reproduce it by merely destroying the model instance. So I doubt that it's relevant here unless you get the same assertion failure.

鉴于你的代码风格,它更可能是你在别处有一个内存错误。如果你认为上面的代码崩溃,你应该有一个自包含的测试用例来演示崩溃。你的模型或委托是怪?它会崩溃使用没有委托?它会崩溃使用股票模型吗?

Given the style of your code, it's more likely that you have a memory bug elsewhere. If you think that the code above is crashing, you should have a self-contained test case that demonstrates the crash. Is your model or delegate to blame? Would it crash using no delegate? Would it crash using a stock model?

您的代码摘录似乎很好,如果大多数是不必要的。您可以在本地分配代理和模型。按钮由视图所有:只要按钮的需要消失,例如当模型更改行计数或离开时,它们将被适当删除。所以你不必自己删除它,它是安全的,但是完全不必要。

Your code excerpt seems to be fine, if mostly unnecessary. You could allocate the delegate and the model locally. The buttons are owned by the view: as soon as the need for the buttons goes away, such as when the model changes the row count or goes away, they will get appropriately deleted. So you don't have to delete them yourself, it's safe but completely unnecessary.

这里有一个例子,说明在所有情况下,按钮将被处置时模型被破坏或视图被破坏,以先到者为准。跟踪对象生命周期在Qt中是超级简单的:保存一组对象,并使用附加到对象的销毁的信号的函子从集合中删除它们。在Qt 4中,您可以使用具有插槽的辅助类。

Here's an example that demonstrates that in all cases, the buttons will get disposed when the model gets destroyed or the view gets destroyed, whichever comes first. Tracking object lifetime is super simple in Qt: keep a set of objects, and remove them from the set using a functor attached to the object's destroyed signal. In Qt 4 you'd use a helper class with a slot.

// 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());
}

这篇关于从QTableView中删除窗口小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆