我刚刚编写了一些基于QThread的代码来执行大计算。为了可视化我需要打开QProgressDialog的进度。该对话框是应用程序模式(使用open()),因为我不想在计算过程中允许修改主窗口。线程发出各种信号,允许GUI和线程之间基于状态机的通信。
线程工作者对象发出的两个信号是" Progress"和"完成"。如果" Progress"发出我正在使用setValue()更新QProgressDialog。如果"完成"发出对话框被破坏。
计算结束时会发生以下情况:
QProgressDialog通过在setValue()中调用processEvents()来破坏我的架构。我的编码约定也禁止使用任何嵌套的事件循环(比如exec()等。)。
我有两个问题:
为什么模态对话框需要嵌套的事件循环?从我未完成的阻止父窗口'输入似乎不需要这个。
是否可以以模态方式使用QProgressDialog但没有嵌套的事件循环?
答案 0 :(得分:1)
您应该使用deleteLater()
来销毁QProgressDialog
。删除QProgressDialog
对象的事件是在属于QProgressDialog
对象本身的函数内处理的,这归结为在c ++成员函数中调用delete this;
的合法性,您可以参考有关此内容的详细信息,请参阅isocpp C ++ FAQ中的this question。它的要点是你应该保证在自杀后不再访问该对象的任何成员 ...
因为你无法在Qt的QProgressDialog::setValue()
实现中保证这一点,delete
QProgressBar
这样的事件会在下次访问对象的任何成员时愉快地调用UB(在成员函数中获取时)。 deleteLater
专门用于解决此类问题,因为延迟删除事件是以特殊方式处理的(QCoreApplication::processEvents()
不会选择它们)。这意味着QProgressDialog
对象将在setValue
将控制权返回到事件循环而不是执行setValue
...
在这种情况下始终使用deleteLater
。在事件中使用普通delete
时,必须确保在执行此对象的成员函数时不会处理此事件,并且不会因为从该对象发出信号而执行此事件这个对象(带有直接信号/插槽连接),毕竟信号只是一个成员函数,其实现由Qt的MOC提供)...