打开QMessageBox时,为什么Irrlicht窗口变黑?

时间:2017-01-24 23:17:12

标签: c++ qt irrlicht qmessagebox

我在Qt上下文中使用Irrlicht。为此,我有一个IrrlichtWidget类,它在QWidget中显示一个Irrlicht设备。以下是该课程的相关部分:

class IrrlichtWidget : public QWidget{
Q_OBJECT
public:
    IrrlichtWidget(){
        irr::SIrrlichtCreationParameters params;
        params.DriverType = irr::video::EDT_OPENGL;
        params.WindowId = (void*)winId();
        m_device = irr::createDeviceEx(params);

        setAttribute(Qt::WA_OpaquePaintEvent);

        m_timer = new QTimer;
        m_timer->setInterval(0);
        QObject::connect(m_timer, &QTimer::timeout, [this](){
            m_device->getVideoDriver()->beginScene(true, true, irr::video::SColor(255, 255, 255, 255));
            m_device->getSceneManager()->drawAll();
            m_device->getVideoDriver()->endScene();
            m_device->run();
        });
        m_timer->start();
    }
private:
    irr::IrrlichtDevice *m_device;
    QTimer *m_timer;
}

在我使用QMessageBox之前,这很好用。当我使用这个类编程并希望使用QMessageBox时,我注意到每当消息框打开时,Irrlicht小部件变黑。为了找出发生了什么,我在Irrlicht主循环中插入了QMessageBox,使它看起来像这样:

QObject::connect(m_timer, &QTimer::timeout, [this](){
    m_device->getVideoDriver()->beginScene(true, true, irr::video::SColor(255, 255, 255, 255));
    m_device->getSceneManager()->drawAll();
    m_device->getVideoDriver()->endScene();
    m_device->run();
    QMessageBox::information(this, "Foo", "Bar");
});

当我这样做时,背景是黑色的:

black background with message box

要进行比较,这是完全相同的程序,唯一的区别是它没有QMessageBox

what i want

我尝试将QMessageBox放在Irrlicht的主循环中,在开头,末尾,中间,它总是做同样的事情。它为每种Qt对话框执行此操作:QMessageBoxQFileDialog等。

我还尝试删除构造函数中的setAttribute(Qt::WA_OpaquePaintEvent)行,然后背景为米色而不是黑色。颜色不一样,但问题仍然存在。

似乎QMessageBox以某种方式删除了Irrlicht小部件的内容。它为什么这样做?我该如何解决?

1 个答案:

答案 0 :(得分:0)

问题是QMessageBox的静态函数(如QMessageBox::information)阻塞了主循环,使得Irrlicht小部件变黑。避免这种情况的一种方法是创建QMessageBox对象并使用open()方法打开它。静态函数使用的exec()方法阻塞主循环并使Irrlicht小部件变黑,但open()方法不会阻止主循环,因此它可以工作。

我使用open()创建了一个函数,它与QMessageBox::information完全相同,但与Irrlicht一起使用。由于open()方法不会阻塞主循环,因此我创建的函数使用lambdas和finished信号来处理消息框关闭后发生的事情。以下是该函数以及如何使用它的示例:

#include <QMessageBox>
#include <functional>

void showMessageBox(std::function<void(QMessageBox::StandardButton)> lambda, QWidget *parent, const QString &title, const QString &text, QMessageBox::Icon icon = QMessageBox::Information, QFlags<QMessageBox::StandardButton> buttons = QMessageBox::Ok){
    QMessageBox *messageBox = new QMessageBox(icon, title, text, buttons, parent);
    messageBox->open(NULL, NULL);
    QObject::connect(messageBox, &QMessageBox::finished, [messageBox, lambda](){
        if(messageBox->clickedButton() == messageBox->button(QMessageBox::Ok)){
            lambda(QMessageBox::Ok);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::Open)){
            lambda(QMessageBox::Open);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::Save)){
            lambda(QMessageBox::Save);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::Cancel)){
            lambda(QMessageBox::Cancel);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::Close)){
            lambda(QMessageBox::Close);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::Discard)){
            lambda(QMessageBox::Discard);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::Apply)){
            lambda(QMessageBox::Apply);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::Reset)){
            lambda(QMessageBox::Reset);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::RestoreDefaults)){
            lambda(QMessageBox::RestoreDefaults);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::Help)){
            lambda(QMessageBox::Help);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::SaveAll)){
            lambda(QMessageBox::SaveAll);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::Yes)){
            lambda(QMessageBox::Yes);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::YesToAll)){
            lambda(QMessageBox::YesToAll);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::No)){
            lambda(QMessageBox::No);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::NoToAll)){
            lambda(QMessageBox::NoToAll);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::Abort)){
            lambda(QMessageBox::Abort);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::Retry)){
            lambda(QMessageBox::Retry);
        }
        else if(messageBox->clickedButton() == messageBox->button(QMessageBox::Ignore)){
            lambda(QMessageBox::Ignore);
        }
        else{
            lambda(QMessageBox::NoButton);
        }
    });
}

以下代码询问用户是否要打开新对话框。如果用户单击是,则会打开一个对话框,显示“Hello World!”,否则没有任何反应。

IrrlichtWidget myWidget = new IrrlichtWidget;    //IrrlichtWidget is the class mentioned in the question
showMessageBox([](QMessageBox::StandardButton result){
    if(result == QMessageBox::Yes){
        showMessageBox([](QMessageBox::StandardButton){}, myWidget, "Hello", "Hello world!");
    }
}, myWidget, "Title", "Do you want to open a new dialog box?", QMessageBox::Question, QMessageBox::Yes | QMessageBox::No);