C++ 如何在静态单例类中以编程方式从exec方法返回
我正在SBC6000x板上开发Qt应用程序(Qt版本4.7.3) 我有一个从QDialog派生的MessageBox类。我把这门课改成了单身 无论何时显示messagebox,我都使用.exec方法来显示它 很少有地方需要一个接一个地显示MessageBox 所以,要显示新的messagebox,我必须关闭前一个messagebox并显示新的messagebox e、 g.当Messagebox打开,同时我从后台收到一个错误时,我必须关闭当前显示的Messagebox并显示有错误的Messagebox 为了关闭上一个对话框,我从messagebox类中公开了CloseDlg方法并试图关闭它 在这个封闭的房间里,我发出了结束的信号C++ 如何在静态单例类中以编程方式从exec方法返回,c++,qt,singleton,qdialog,C++,Qt,Singleton,Qdialog,我正在SBC6000x板上开发Qt应用程序(Qt版本4.7.3) 我有一个从QDialog派生的MessageBox类。我把这门课改成了单身 无论何时显示messagebox,我都使用.exec方法来显示它 很少有地方需要一个接一个地显示MessageBox 所以,要显示新的messagebox,我必须关闭前一个messagebox并显示新的messagebox e、 g.当Messagebox打开,同时我从后台收到一个错误时,我必须关闭当前显示的Messagebox并显示有错误的Message
void CMsgBox::CloseDlg()
{
if (NULL != CMsgBox::m_msgBox)
{
if(CMsgBox::m_msgBox->isVisible())
{
emit CMsgBox::m_msgBox->finished(0);
//QApplication::processEvents();
}
}
}
并称之为
CMsgBox::CloseDlg();
我的展示方式是:-
int CMsgBox::showMsgBox(Icon icon, const QString &textMsg, const QString &okBtnText)
{
if (CMsgBox::m_msgBox == NULL)
{
CMsgBox::m_msgBox = new CMsgBox();
}
CMsgBox::m_msgBox->setText(textMsg);
CMsgBox::m_msgBox->setIcon(icon);
CMsgBox::m_msgBox->setOkBtnText(okBtnText);
CMsgBox::m_msgBox->exec();
return CMsgBox::m_msgBox->m_btnPressed; //return, unblock the call
}
当我再次调用showMsgBox时,它会向我显示以下警告。
QDialog::exec:检测到递归调用
问题是,它不会从上一个exec调用返回(除非我们返回,如上所述/)
我尝试了close()、accept()、reject()方法,而不是finished()事件,但没有任何效果
如何从先前的exe调用返回并实现上述场景?欢迎任何帮助。因此,您需要帮助。如其文件中所述:
使用show()显示无模式对话框,它会立即将控制权返回给调用方
因此,不要用
exec()
显示框,而是用show()
显示框。另一个答案中建议的show()方法的替代方法是使用。它将返回,但仍然会给您提供模式对话框,因此在您关闭它之前,GUI的其余部分将被禁用。您在这里看到的看起来像是竞争条件。模态QDialog运行自己的事件循环,因此您的应用程序的行为类似于多线程应用程序,您需要注意并发性和竞争条件
当您在主事件循环中接收到第二个事件时,可以快速连续调用CMsgBox::CloseDlg()
和CMsgBox::showMsgBox()
。但是,CloseDlg()
告诉对话框的事件循环返回,但是CloseDlg()
实际上在对话框的事件循环清理完成之前返回,并且showMsgBox()
尝试对尚未完成退出的对话框调用exec()
你需要做的是,当你调用CMsgBox::CloseDlg()
时,连接到finished(int)
信号,只有当你收到finished(int)
时,你才能安全地exec()
再次打开对话框
注意:连接到
finished(int)
信号时,请确保使用Qt::QueuedConnection
而不是默认的Qt::DirectConnection
。如果由于性能原因,应用程序显示的错误消息太多,需要单音消息框来显示这些消息。。。用户将看到什么?最后一个错误?一个接一个的错误?它被称为ErrorOnlyApplication?错误是一种罕见的情况。用户应该能够看到带有指定错误的最新消息框。那么为什么要保留消息框的分配?你有内存碎片问题吗?如果在运行时创建窗口,我会在应用程序开始时创建所有窗口,并在需要时显示它们。这还包括一个messagebox。(我知道这不是完美的方法,我正在保存创建屏幕的运行时处理并投资于内存使用)您是否尝试过在运行时更改消息框的文本?(不知道这是否有效)。作为一个侧节点,我推荐阅读,它确实改变了我对单音的看法谢谢你,我只想让它保持模态。保持无模式立即返回。如果我有两个按钮确定和取消和取消是我的默认值。它立即返回该值,这是不期望的。我只想将其保持为模态。保持无模式立即返回。如果我有两个按钮确定和取消和取消是我的默认值。它会立即返回该值,这是不期望的。谢谢你,弗雷德,我试过了。在收到“finished”事件后,我试图调用exec,但它仍然给了我“QDialog::exec:检测到递归调用”。我认为,它不能立即脱离其状态,并且作为一个单态对象,它会妨碍下一次调用。我们需要找到一个对象上可调用exec的逻辑点,它没有任何等待条件。@RajendraW:当附加到“finished”信号时,您是否确保该序列为排队序列而不是默认的直接连接类型?这里使用“multithreaded”和“concurrency”有点误导。本地事件循环在exec()内完全同步执行,但由于任何事件都可能发生并触发任意事件处理程序/插槽,因此在exec()返回并销毁对应用程序状态所做的任何假设之前,都可以执行(在同一线程中)。这与临界截面相似,是的。OTOH它也简单得多,而锁定等多线程概念也无助于解决这个问题。最简单的方法是:不要弄乱事件循环:不要使用exec()、processEvents()或显式本地事件循环。@Fred:您的解决方案工作得很好,使用Qt::QueuedConnection的connect调用有助于使用“done”函数关闭第一个messagebox。一旦第一个接收到“完成”信号,我们就可以显示下一个messagebox。