如何在静态单例类中以编程方式从exec方法返回

How to return from exec method programmatically in static singleton class

本文关键字:方式 exec 方法 返回 编程 静态 单例类      更新时间:2023-10-16

我正在SBC6000x板上开发Qt应用程序(Qt版本4.7.3)。

我有一个从QDialog派生的MessageBox类。我已经使这个类成为singleton。

每当要显示消息框时,我都会使用.exec方法来显示它。

很少有地方需要我一个接一个地显示消息框。

所以,要显示新的消息框,我必须关闭前一个并显示新的。

例如,当Messagebox打开,同时我从后台收到错误时,我必须关闭当前显示的Messagebox,并显示有错误的Messagebox。

为了关闭上一个对话框,我公开了messagebox类中的CloseDlg方法,并试图关闭它

在这个CloseDlg里面,我正在发射完成的信号。

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时,它会向我显示以下警告。Q对话框::exec:检测到递归调用

问题是,它不会从以前的exec调用中返回(除非我们返回,如上所述//)。

我尝试了close()、accept()、reject()方法,而不是finished()事件,但都没有成功。

从以前的exe调用返回并实现上述场景的方法是什么?欢迎任何帮助。

这里的内容看起来像是一个竞赛条件。模式QDialog运行自己的事件循环,因此您的应用程序的行为就像一个多线程应用程序,您需要注意并发性和竞争条件。

当您在主事件循环中收到第二个消息时,您会快速连续地呼叫CMsgBox::CloseDlg()CMsgBox::showMsgBox()。然而,CloseDlg()告诉对话框的事件循环返回,但CloseDlg()实际上在对话框的事件环路完成清理之前返回,并且showMsgBox()尝试在尚未完成退出的对话框上调用exec()

你需要做的是,当你呼叫CMsgBox::CloseDlg()时,连接到finished(int)信号,只有当你收到finished(int)时,你才能安全地再次exec()对话框。

注意:当连接到finished(int)信号时,请确保使用Qt::QueuedConnection而不是默认的Qt::DirectConnection

因此,您需要无模式对话框。如文件所述:

使用show()显示无模型对话框,该对话框会立即将控制权返回给调用方。

因此,与其用exec()显示框,不如用show()显示框。

另一个答案中建议的show()方法的替代方法是使用QDialog::open()。它将返回,但仍将为您提供模式对话框,因此GUI的其余部分将被禁用,直到您关闭它