0

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

我有一个从 QDialog 派生的 MessageBox 类。我已经将这个类设为单例。

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

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

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

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

为了关闭上一个对话框,我从 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 调用返回并实现上述场景的方法是什么?欢迎任何帮助。

4

3 回答 3

1

您在这里所拥有的看起来像是一种竞争条件。模态 QDialog 运行自己的事件循环,因此您的应用程序的行为类似于多线程应用程序,您需要注意并发和竞争条件。

当您在主事件循环中收到一秒钟时,您会CMsgBox::CloseDlg()快速CMsgBox::showMsgBox()连续调用。但是,CloseDlg()告诉对话框的事件循环返回,但CloseDlg()实际上在对话框的事件循环完成清理之前返回,并showMsgBox()尝试调用exec()尚未完成退出的对话框。

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

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

于 2012-12-11T18:16:45.823 回答
0

所以,你需要无模式对话框。如他们的文档中所述:

使用 show() 显示无模式对话框,它立即将控制权返回给调用者。

因此,不要用 来显示框,而是用 来exec()显示它show()

于 2012-12-11T09:18:00.247 回答
0

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

于 2012-12-11T09:22:46.127 回答