在我正在从事的项目中,Qt 5.15.2 与 C++ 一起使用。不幸的是,我找不到触发删除对象的事件?
什么可以触发下面给出的 lambda 函数?
auto deletionConnection = connect(myCustomQObject, &QWidget::deleted, [myCustomQObject, this, serverName] (){
communicationDeleted(serverName);
});
很明显,当 myCustomQObject 对象被删除时,程序执行进入到这个 lambda 函数内部。 communicationDeleted(serverName) 是另一个信号。 但我找不到删除此 myCustomQObject 对象的事件。下面给出了包含此连接的代码块。
void myCustomTableWidget::addRow(const QString& serverName)
{
myCustomQObject* newCustomQObject = new myCustomQObject(this);
QWidget* newCellWidget = new QWidget();
QHBoxLayout* rowLayout = new QHBoxLayout(newCellWidget);
rowLayout->addWidget(myCustomQObject);
newCellWidget->setLayout(rowLayout);
m_ui->tableServers->insertRow(m_rowCount);
m_ui->tableServers->setCellWidget(newCellWidget);
auto deletionConnection = connect(myCustomQObject, &QWidget::deleted, [myCustomQObject, this, serverName] (){
communicationDeleted(serverName);
});
m_->deletionConnections.pushBack(deletionConnection);
...
}
我怀疑另一个插槽 myCustomTableWidget::deleteRow(qint32) 导致对象被删除。但是,如果我在桌子上有多个项目并删除其中三个,则执行会进入 deleteRow(qint32) 中设置的断点三次。然而,我看到在该过程的后期,lambda 被执行。我说得对吗,从表中删除一行会导致项目对象被删除?或者我应该关注不同的地方?
void myCustomTableWidget::deleteRow(qint32 rowIndex)
{
m_ui->tableServers->removeRow(rowIndex);
m_rowCount--;
}
在Qt的
QTableWidget
中,setCellWidget()
内部调用setIndexWidget()
的
QAbstractItemView
。这又将小部件注册为“静态编辑器”。
当在 Qt 项目视图中删除任何模型项目时,将调用
rowsAboutToBeRemoved()
的 QAbstractItemView
插槽。这又会调用小部件上的d->releaseEditor()
。对于静态编辑器,releaseEditor()
函数调用editor->deleteLater()
来实际删除小部件。
QObject
的所有子类都有一个deleteLater()
槽。存在这种情况的原因如下:假设您的小部件是一个按钮,并且您将该按钮的 clicked()
信号与一个插槽连接起来,该插槽会删除小部件所在的行。如果项目视图仅调用 delete widget;
,则小部件将被删除,而其自己的 clicked()
信号事件处理程序仍处于活动状态。这可能会导致内存损坏,因为您不应该删除仍在使用的对象。 Qt 通过在许多地方使用 deleteLater()
来避免这些类型的问题:对象被标记为要删除,但只有当控制权返回给事件循环时(即当前事件处理程序已退出),所有对象都以这种方式标记为删除也被删除,现在可以安全地执行此操作,因为这些对象不再被使用。
(顺便说一句,这就是为什么
dialog.exec()
和/或 QApplication::processEvents()
在某些情况下会导致奇怪的错误。)