我正在SBC6000x主板上开发Qt应用程序(Qt版本4.7.3)。
我有一个从QDialog派生的MessageBox类。我已经使这个班级单身。
每当要显示一个消息框时,我都会使用.exec方法来显示它。
我需要一个接一个地展示留言箱的地方。
因此,要显示新的消息框,我必须关闭上一个消息框并显示新消息框。
e.g。当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时,它会向我显示以下警告。 QDialog :: exec:检测到递归调用
问题是,它不会从之前的exec调用返回(除非我们返回,如上面评论的那样//)。
我尝试使用close(),accept(),reject()方法而不是finished()事件,但没有任何效果。
从上一个exe调用返回并实现上述场景的方法是什么?欢迎任何帮助。
答案 0 :(得分:1)
你在这里看起来像一个竞争条件。模态QDialog运行自己的事件循环,因此您的应用程序的行为类似于多线程应用程序,您需要处理并发和竞争条件。
当您在主要事件循环中收到第二个时,您会快速连续致电CMsgBox::CloseDlg()
和CMsgBox::showMsgBox()
。但是,CloseDlg()
告诉对话框的事件循环返回,但CloseDlg()
实际上在对话框的事件循环完成清理之前返回,showMsgBox()
尝试在对话框上调用exec()
还没有完成退出。
当您致电CMsgBox::CloseDlg()
时,您需要做的是连接到finished(int)
信号,并且只有在您收到finished(int)
后才能安全地exec()
对话试。
注意:连接到finished(int)
信号时,请务必使用Qt::QueuedConnection
代替默认的Qt::DirectConnection
。
答案 1 :(得分:0)
所以,你需要modeless dialog box。正如他们的文档中所解释的那样:
使用show()显示无模式对话框,它会立即将控制权返回给调用者。
因此,不要使用exec()
显示框,而是使用show()
显示该框。
答案 2 :(得分:0)
另一个答案建议的show()方法的替代方法是,使用QDialog::open()
。它将返回,但仍然会给你模态对话框,因此GUI的其余部分将被禁用,直到你关闭它。