C++ 模态QProgressDialog::setValue()通过嵌套事件循环导致崩溃
我刚刚编写了一些基于QThread的代码,执行了一个大的计算。要可视化进度,我需要打开一个QProgressDialog。该对话框是应用程序模式(使用open()),因为我不希望在计算期间修改主窗口。线程发出各种信号,允许GUI和线程之间基于状态机的通信 线程的worker对象发出的两个信号是“Progress”和“Finished”。如果发出“Progress”,我将使用setValue()更新QProgressDialog。如果发出“完成”,则对话框将被销毁 计算结束时发生以下情况:C++ 模态QProgressDialog::setValue()通过嵌套事件循环导致崩溃,c++,qt,qeventloop,queued-connection,qprogressdialog,C++,Qt,Qeventloop,Queued Connection,Qprogressdialog,我刚刚编写了一些基于QThread的代码,执行了一个大的计算。要可视化进度,我需要打开一个QProgressDialog。该对话框是应用程序模式(使用open()),因为我不希望在计算期间修改主窗口。线程发出各种信号,允许GUI和线程之间基于状态机的通信 线程的worker对象发出的两个信号是“Progress”和“Finished”。如果发出“Progress”,我将使用setValue()更新QProgressDialog。如果发出“完成”,则对话框将被销毁 计算结束时发生以下情况: 发出
- 发出“进度”事件(100%)
- “Finished”(完成)是在
- 由于“进度”事件而调用setValue(100)
- 因为对话框是模态的,所以setValue()调用processEvents()
- processEvents()传递“已完成”事件
- “完成”事件导致对话框在中间被破坏。 导致崩溃的setValue()的
您应该使用
deleteLater()
销毁QProgressDialog
。删除QProgressDialog
对象的事件在属于QProgressDialog
对象本身的函数中处理,这归结为调用delete this的合法性代码>在C++成员函数中,您可以从iSoCP++ C++ FAQ中参考有关此的更多信息。其要点是,你应该保证在自杀后不再访问该对象的任何成员
由于在Qt的QProgressDialog::setValue()
实现中无法保证这一点,因此delete
sQProgressBar
这样的事件将在下次访问对象的任何成员时(在成员函数中拾取时)愉快地调用UBdeleteLater
是专门为解决这类问题而设计的,因为延迟删除事件是以特殊方式处理的(它们不会被QCoreApplication::processEvents()
拾取)。这意味着<代码> qPrimeStReals< /Cord>对象将在<代码> SETValue/COD>之后被返回到事件循环中,而不是在执行<代码> SETValue…< /P>的中间。
在这种情况下,请始终使用deleteLater
。在事件中使用plaindelete
时,您必须确保在执行此对象的成员函数时不会处理此事件,并且不会因为从该对象发出信号(使用直接信号/插槽连接)而执行此事件,因为,信号只是一个成员函数,其实现由Qt的MOC提供).如何“破坏”对话框?您是否正在使用deleteLater()
?您的问题标题与实际编号的问题不匹配。请让它们保持一致。@Mike:我使用delete。也许deleteLater是一种解决方法,我会尽快尝试。setModal()/show()在这里不起作用。我已经使用open()。QProgressDialog很特别,因为不管我使用哪种模态,它都会调用setValue()中的事件循环。@Silicomancer,那么,嵌套事件循环与您描述的崩溃无关。无论如何,我已经回答了您关于在没有嵌套事件循环的情况下设置模式对话框的问题(我是否正确回答了您的问题?),使用open()
似乎也是另一种方式……对不起,Mike,但我想您没有回答这个问题。我知道如何在没有事件循环的情况下设置模态对话框。我的问题是如何设置没有事件循环的模式QProgressDialog。但我想这根本不可能,因为QProgressDialog::setValue()的特殊行为。也许稍后删除是一个很好的解决方法。我会在尝试后给出反馈。我同意。我会努力的。Qt人员决定通过实现嵌套循环来支持设计糟糕的应用程序,这真是太糟糕了。我认为他们应该放弃对这些残破建筑的支持。如果您删除/编辑答案中的模态部分(不适用于我的情况),我可以接受您的解决方案。@Silicomancer,我已删除了答案中有关模态的部分。但我认为你也必须把它们从你的问题中删除。具体来说,最后的两个问题似乎与您已经在使用open()
以及您知道如何在没有嵌套事件循环的情况下设置模式对话框的事实相冲突。。。