问题
My class names is like (what it does)_(type) for example: reg_QDialog
Here is code of an executing dlg and if Accepted creating QMainWindow:
if(log_dlg->exec() == QDialog::Accepted)
{
find_wnd = new find_QMainWindow();
find_wnd->show();
}
log_dlg has 2 btns: "Enter" (here is the accept result) and "Reg" (opens a new dlg)
"Enter" and "Reg" code is here:
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();
}
So, here is the problem:
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
After "returning"(it's, actually, just hiding and then showing) from the reg_dlg and pushing btn with accept result it does nothing! It just closes the programm, but it had to show QMainWindow!
All real code of 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();
}
回答1:
You are a operating a bit beyond the limits of Qt. Looking at the documentation:
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.
Testing your code on Mac OS will give you the dreaded warning
modalSession has been exited prematurely - check for a reentrant call to endModalSession
which shows, that you are working on thin ice and your code will break any time.
Consider reworking your code so that the MainWindow comes up and then show your dialogs. If you want to go on with the Dialog sequence, then remove the hide()/show() pair from on_btn_reg_clicked (these calls mess up your event loops).
回答2:
QApplication exits and close when the last window has been closed. You can discard this by setting QApplication::quitOnLastWindowClosed property to false.
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
You may want to revert it to it's previous state when your job is done with those dialogs.
As @Jens mentioned in the other answer to your question, this is will break evenloop at some point and QApplication exits before even a.exec() being called. So, you can also create a zero width/height or off-screen 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.
回答3:
[Re-posting from duplicate-closed question since the top banner on it may cause people to skip that question entirely, and IMHO this one doesn't have a good answer.]
Here's a very simple example of showing a dialog before a QMainWindow
. The dialog simply presents the option of starting the main app or not. They key points are that the QDialog portion happens before any other widgets are created (eg. QMainWindow here), and the app (main()
) exits before that if needed. No reason to keep the QDialog around after it is used, so I create it on the stack and delete
afterwards.
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();
}
来源:https://stackoverflow.com/questions/58571952/qdialog-closing-on-its-own-how-can-i-fix-it