【问题标题】:Why does the Irrlicht window turn black when opening a QMessageBox?为什么打开 QMessageBox 时 Irrlicht 窗口会变黑?
【发布时间】:2017-01-24 23:17:12
【问题描述】:

我在 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");
});

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

为了比较,这里是完全相同的程序,唯一的区别是它没有QMessageBox

我尝试将 QMessageBox 放在 Irrlicht 的主循环中的任何地方,在开头、结尾、中间,它总是做同样的事情。它对各种 Qt 对话框都执行此操作:QMessageBoxQFileDialog 等。

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

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

【问题讨论】:

    标签: c++ qt irrlicht qmessagebox


    【解决方案1】:

    问题是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);
    

    【讨论】:

      猜你喜欢
      • 2011-12-24
      • 2014-12-01
      • 2020-04-04
      • 2015-05-12
      • 1970-01-01
      • 2021-06-19
      • 2019-06-11
      • 1970-01-01
      • 2018-06-04
      相关资源
      最近更新 更多