QDialog 自行关闭,我该如何解决?
QDialog closing on it's own, how can i fix it?
我的 class 名字就像(它的作用)_(类型)例如:reg_QDialog
这是正在执行的 dlg 的代码,如果接受则创建 QMainWindow:
if(log_dlg->exec() == QDialog::Accepted)
{
find_wnd = new find_QMainWindow();
find_wnd->show();
}
log_dlg 有 2 个 btns:"Enter"(这里是接受结果)和 "Reg"(打开一个新的 dlg)
"Enter" 和 "Reg" 代码在这里:
void log_QDialog::on_btn_enter_clicked()
{
this->accept();
}
void log_QDialog::on_btn_reg_clicked()
{
reg_QDialog *reg_dlg = new reg_QDialog();
this->hide();
if(reg_wnd->exec() == QDialog::Accepted)
{
//code
}
this->show();
}
那么,问题来了:
Step by step:
1) run the prog //it starts with dlg_log
2) "Reg" //creating dlg_reg
3) accept dlg_reg //returning to dlg_log
4) "Enter" //trying to create QMainWindow
QMainWindow is not created, and the app just closed
在 "returning"(实际上只是隐藏然后显示)之后,从 reg_dlg 并使用接受结果推送 btn 它什么都不做!它只是关闭程序,但它必须显示 QMainWindow!
main.cpp的所有真实代码:
#include "log_window_root.h"
#include "find_mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
log_window_root * log_wnd;
find_mainwindow * find_wnd;
log_wnd = new log_window_root();
log_wnd->setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
log_wnd->setModal(true);
if(log_wnd->exec() == QDialog::Accepted)
{
find_wnd = new find_mainwindow();
find_wnd->setWindowFlags(Qt::MSWindowsFixedSizeDialogHint);
find_wnd->show();
}
return a.exec();
}
QApplication 在最后一个 window 关闭时退出并关闭。
您可以通过将 QApplication::quitOnLastWindowClosed 属性 设置为 false 来丢弃它。
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
您可能希望在使用这些对话框完成工作后将其恢复到之前的状态。
正如@Jens 在您的问题的另一个答案中提到的那样,这将在某些时候打破 evenloop,并且 QApplication 甚至在 a.exec() 被调用之前退出。因此,您还可以创建一个零 width/height 或离屏 QWidget as a parent of your dialogs. A QSplashScreen is also a good candidate for this. All your dialogs should be your splash screen children. At last, you can finish your splash screen by calling QSplashScreen::finish.
你的操作有点超出了Qt的极限。查看文档:
Generally, no user interaction can take place before calling exec().
As a special case, modal widgets like QMessageBox can be used before
calling exec(), because modal widgets call exec() to start a local
event loop.
在 Mac OS 上测试你的代码会给你可怕的警告
modalSession has been exited prematurely - check for a reentrant call
to endModalSession
这表明您的工作如履薄冰,您的代码随时都会崩溃。
考虑修改您的代码,以便出现 MainWindow,然后显示您的对话框。如果您想继续 Dialog 序列,请从 on_btn_reg_clicked 中删除 hide()/show() 对(这些调用会弄乱您的事件循环)。
[重新发布 duplicate-closed 问题,因为它的顶部横幅可能会导致人们完全跳过该问题,恕我直言,这个问题没有很好的答案。]
这是一个在 QMainWindow
之前显示对话框的非常简单的示例。该对话框仅显示是否启动主应用程序的选项。他们的关键点是 QDialog 部分发生在创建任何其他小部件之前(例如这里的 QMainWindow),并且如果需要,应用程序(main()
)在此之前退出。没有理由在使用后保留 QDialog,所以我在堆栈上创建它,然后 delete
。
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDialog *d = new QDialog();
QPushButton *pbYes = new QPushButton("Would you like to play a game?", d);
QPushButton *pbNo = new QPushButton("Get me out of here!", d);
QObject::connect(pbYes, &QPushButton::clicked, [d]() { d->done(QDialog::Accepted); });
QObject::connect(pbNo, &QPushButton::clicked, [d]() { d->done(QDialog::Rejected); });
d->setLayout(new QVBoxLayout);
d->layout()->addWidget(pbYes);
d->layout()->addWidget(pbNo);
const int ret = d->exec();
delete d;
if (ret == QDialog::Rejected)
return 0;
QMainWindow mw;
mw.setCentralWidget(new QLabel("Welcome to the Game!", &mw));
mw.show();
return a.exec();
}
我的 class 名字就像(它的作用)_(类型)例如:reg_QDialog
这是正在执行的 dlg 的代码,如果接受则创建 QMainWindow:
if(log_dlg->exec() == QDialog::Accepted)
{
find_wnd = new find_QMainWindow();
find_wnd->show();
}
log_dlg 有 2 个 btns:"Enter"(这里是接受结果)和 "Reg"(打开一个新的 dlg)
"Enter" 和 "Reg" 代码在这里:
void log_QDialog::on_btn_enter_clicked()
{
this->accept();
}
void log_QDialog::on_btn_reg_clicked()
{
reg_QDialog *reg_dlg = new reg_QDialog();
this->hide();
if(reg_wnd->exec() == QDialog::Accepted)
{
//code
}
this->show();
}
那么,问题来了:
Step by step:
1) run the prog //it starts with dlg_log
2) "Reg" //creating dlg_reg
3) accept dlg_reg //returning to dlg_log
4) "Enter" //trying to create QMainWindow
QMainWindow is not created, and the app just closed
在 "returning"(实际上只是隐藏然后显示)之后,从 reg_dlg 并使用接受结果推送 btn 它什么都不做!它只是关闭程序,但它必须显示 QMainWindow!
main.cpp的所有真实代码:
#include "log_window_root.h"
#include "find_mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
log_window_root * log_wnd;
find_mainwindow * find_wnd;
log_wnd = new log_window_root();
log_wnd->setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
log_wnd->setModal(true);
if(log_wnd->exec() == QDialog::Accepted)
{
find_wnd = new find_mainwindow();
find_wnd->setWindowFlags(Qt::MSWindowsFixedSizeDialogHint);
find_wnd->show();
}
return a.exec();
}
QApplication 在最后一个 window 关闭时退出并关闭。 您可以通过将 QApplication::quitOnLastWindowClosed 属性 设置为 false 来丢弃它。
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
您可能希望在使用这些对话框完成工作后将其恢复到之前的状态。
正如@Jens 在您的问题的另一个答案中提到的那样,这将在某些时候打破 evenloop,并且 QApplication 甚至在 a.exec() 被调用之前退出。因此,您还可以创建一个零 width/height 或离屏 QWidget as a parent of your dialogs. A QSplashScreen is also a good candidate for this. All your dialogs should be your splash screen children. At last, you can finish your splash screen by calling QSplashScreen::finish.
你的操作有点超出了Qt的极限。查看文档:
Generally, no user interaction can take place before calling exec(). As a special case, modal widgets like QMessageBox can be used before calling exec(), because modal widgets call exec() to start a local event loop.
在 Mac OS 上测试你的代码会给你可怕的警告
modalSession has been exited prematurely - check for a reentrant call to endModalSession
这表明您的工作如履薄冰,您的代码随时都会崩溃。
考虑修改您的代码,以便出现 MainWindow,然后显示您的对话框。如果您想继续 Dialog 序列,请从 on_btn_reg_clicked 中删除 hide()/show() 对(这些调用会弄乱您的事件循环)。
[重新发布 duplicate-closed 问题,因为它的顶部横幅可能会导致人们完全跳过该问题,恕我直言,这个问题没有很好的答案。]
这是一个在 QMainWindow
之前显示对话框的非常简单的示例。该对话框仅显示是否启动主应用程序的选项。他们的关键点是 QDialog 部分发生在创建任何其他小部件之前(例如这里的 QMainWindow),并且如果需要,应用程序(main()
)在此之前退出。没有理由在使用后保留 QDialog,所以我在堆栈上创建它,然后 delete
。
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDialog *d = new QDialog();
QPushButton *pbYes = new QPushButton("Would you like to play a game?", d);
QPushButton *pbNo = new QPushButton("Get me out of here!", d);
QObject::connect(pbYes, &QPushButton::clicked, [d]() { d->done(QDialog::Accepted); });
QObject::connect(pbNo, &QPushButton::clicked, [d]() { d->done(QDialog::Rejected); });
d->setLayout(new QVBoxLayout);
d->layout()->addWidget(pbYes);
d->layout()->addWidget(pbNo);
const int ret = d->exec();
delete d;
if (ret == QDialog::Rejected)
return 0;
QMainWindow mw;
mw.setCentralWidget(new QLabel("Welcome to the Game!", &mw));
mw.show();
return a.exec();
}