为什么打开 QMessageBox 时 Irrlicht window 变黑?
Why does the Irrlicht window turn black when opening a QMessageBox?
我在 Qt 上下文中使用 Irrlicht。为此,我有一个 IrrlichtWidget
class,它在 QWidget 中显示了一个 Irrlicht 设备。这是 class:
的相关部分
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
之前,它工作得很好。当我用这个 class 编程并想使用 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 对话框执行此操作:QMessageBox
、QFileDialog
等
我还尝试删除构造函数中的 setAttribute(Qt::WA_OpaquePaintEvent)
行,然后背景变成了米色而不是黑色。不一样的颜色,还是一样的问题
QMessageBox
似乎以某种方式删除了 Irrlicht 小部件的内容。为什么要这样做?我该如何解决?
问题是 QMessageBox
的静态函数(如 QMessageBox::information
)阻塞了主循环,使 Irrlicht 小部件变黑。避免这种情况的一种方法是创建一个 QMessageBox
对象并使用 open()
方法打开它。静态函数使用的 exec()
方法会阻塞主循环并使 Irrlicht 小部件变黑,但是 open()
方法不会阻塞主循环,因此可以正常工作。
我使用 open()
创建了一个函数,它的作用与 QMessageBox::information
相同,但适用于 Irrlicht。由于 open()
方法不会阻塞主循环,我创建的函数使用 lambda 和 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);
我在 Qt 上下文中使用 Irrlicht。为此,我有一个 IrrlichtWidget
class,它在 QWidget 中显示了一个 Irrlicht 设备。这是 class:
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
之前,它工作得很好。当我用这个 class 编程并想使用 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 对话框执行此操作:QMessageBox
、QFileDialog
等
我还尝试删除构造函数中的 setAttribute(Qt::WA_OpaquePaintEvent)
行,然后背景变成了米色而不是黑色。不一样的颜色,还是一样的问题
QMessageBox
似乎以某种方式删除了 Irrlicht 小部件的内容。为什么要这样做?我该如何解决?
问题是 QMessageBox
的静态函数(如 QMessageBox::information
)阻塞了主循环,使 Irrlicht 小部件变黑。避免这种情况的一种方法是创建一个 QMessageBox
对象并使用 open()
方法打开它。静态函数使用的 exec()
方法会阻塞主循环并使 Irrlicht 小部件变黑,但是 open()
方法不会阻塞主循环,因此可以正常工作。
我使用 open()
创建了一个函数,它的作用与 QMessageBox::information
相同,但适用于 Irrlicht。由于 open()
方法不会阻塞主循环,我创建的函数使用 lambda 和 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);