关闭部件的Qt析构函数调用

Qt destructor call for closed widget

本文关键字:析构 函数调用 Qt 闭部      更新时间:2023-10-16

有一个处理文本命令的应用程序。我有一个Qt小部件,是关闭一些close *命令。Qt::WA_DeleteOnClose属性为该小部件设置,它接收closeEvent,但该对象的析构函数稍后被调用(我猜是在空闲时)。如果我有两个命令close *; get something;程序崩溃,因为get something在该小部件的析构函数之前被调用,因此它试图访问由close *命令删除的数据。我怎样才能强制Qt调用析构函数?关闭命令后的QCoreApplication::processEvents()没有帮助。在将qt版本从4.3.3更改为4.7.2后,我遇到了这个问题。这里没有多线程。

提前感谢。

添加

下面是代码示例:

test *t = new test();
t->show();
std::cout << "before deleteLater()" << std::endl;
t->deleteLater();
std::cout << "after deleteLater()" << std::endl;
QCoreApplication::sendPostedEvents();
QCoreApplication::processEvents();
std::cout << "after processEvents()" << std::endl;

测试类派生自QDialog。它在构造函数中输出test(),在析构函数中输出~test()。这段代码给出了以下输出

test()
before deleteLater()
after deleteLater()
after processEvents()
~test()

根据Qt文档,它应该删除对象之前最后计数,我是对的吗?看起来像是Qt里的一个bug,有人知道吗?有解决方案吗?

我在Qt邮件列表中问了这个问题,但仍然在等待答案。

谢谢。

再更新一次

这段代码

Dialog::~Dialog() {
    std::cout << "~test()" << std::endl;
}
int main(int argc, char* argv[]) {
    QApplication app(argc, argv);
    Dialog* dlg = new Dialog();
    dlg->setAttribute(Qt::WA_DeleteOnClose);
    dlg->show();
    dlg->close();
    std::cout << "before sendPostedEvents()" << std::endl;
    QCoreApplication::sendPostedEvents();
    std::cout << "after sendPostedEvents()" << std::endl;
    return app.exec();
}

打印这个

before sendPostedEvents()
after sendPostedEvents()
~test()

但只要我添加closeEvent处理程序并在该处理程序函数中调用deleteLater(), sendPostedEvents就会开始删除延迟对象。

void Dialog::closeEvent(QCloseEvent* ev) {
    deleteLater();
    QWidget::closeEvent(ev);
}

打印之前sendPostedEvents ()~测试()后sendPostedEvents ()

谁能解释一下这到底是怎么回事?这只是一个bug吗?我可以用它作为变通方法吗?

这是如何工作的?不应该Qt调用deleteLater()自动,closeEvent被接受后,如果CloseOnDelete属性设置?

设置Qt::WA_DeleteOnClose意味着qt可以在调用close()后随时删除,因为qt内部使用deleteLater()。可以使用QObject::destroyed()信号确保删除

QCoreApplication:: procesevents显式跳过关闭事件的删除。您需要将QEventLoop::DeferredDeletion传递给processEvents()。例如QCoreApplication: processEvents (QEventLoop:: DeferredDeletion);