介绍
你好在我的应用程序中,我在MainWindow的构造函数完成之前运行QDialog。根据此QDialog中的用户输入,我要关闭该应用程序。
问题
由于QApplication事件循环尚未开始,因此我无法调用qApp->quit()
或qApp->exit(int retcode = 0)
。有没有一种方法可以强制MainWindow退出?还是等到它完全加载后再退出?
解决方案?
我设法使其工作,但我不知道为什么。这是我现在的QDialog的.cpp:
QFileInfo checkConfig(configPath);
if(!checkConfig.exists() || !checkConfig.isFile())
{
qDebug() << "Sair!";
qApp->quit();
//qApp->exit(1);
//QTimer::singleShot(0, qApp, &QCoreApplication::quit);
QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
}
使用
QTimer::singleShot(0, qApp, &QCoreApplication::quit)
,QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection)
,qApp->quit()
或qApp->exit(1)
没有任何作用。但是,由于某些原因,使用(
qApp->quit()
或qApp->exit(1)
)和(QTimer::singleShot(0, qApp, &QCoreApplication::quit)
或QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection)
)可行!我觉得使用此解决方案可以稍后再次吸引我,因为我不知道它是如何工作的。有谁有更好的解决方案或解释?
编辑
单独调用
QTimer::singleShot(0, qApp, &QCoreApplication::quit)
并不能关闭我的应用程序。虽然,第二次我通过该函数,但它确实关闭了。 QTimer::singleShot()
在重新实现的QDialog::reject
方法上。而且,在关闭之前,我会显示QMessageBox
。任何这些都会干扰QTimer
吗?编辑2
我运行了示例@ user3606329展示。确实可以。我进一步走了几步,并在此程序的另一个程序中使用了自己的
QDialog
。它确实没有用。所以问题出在我的QDialog
中?下面是整个reject
方法:void Configuracao::reject()
{
QFileInfo checkConfig(configPath);
if(!checkConfig.exists() || !checkConfig.isFile())
{
QMessageBox::critical(this,"Erro na configuração","Erro na criação do aquivo config.ini.\n"
"O programa será finalizado!");
qDebug() << "Sair!";
//qApp->quit();
//qApp->exit(1);
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
//QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
}
}
编辑3
我决定再创建一个
QDialog
,然后仅创建,用QTimer::singleShot
重新实现拒绝方法。它仍然没有用。第一次调用拒绝时,它经历了QTimer::singleShot
并没有执行任何操作(甚至没有关闭对话框)。第二次,它关闭对话框并关闭了应用程序。有什么想法吗? (下面的代码)mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "dialog.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
Dialog *conf;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
conf = new Dialog(this);
conf->exec();
}
MainWindow::~MainWindow()
{
delete ui;
}
dialog.h:
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private:
Ui::Dialog *ui;
protected:
void reject();
};
#endif // DIALOG_H
dialog.cpp:
#include "dialog.h"
#include "ui_dialog.h"
#include <QTimer>
#include <QDebug>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::reject()
{
QTimer::singleShot(0, qApp, []() {
qDebug() << "QTimer done";
QCoreApplication::quit();
});
}
main.cpp:
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
qDebug() << "Event loop started";
return a.exec();
}
输出:
QTimer done //first click on "close window"
Event loop started //first click on "close window"
QTimer done //second click on "close window"
最佳答案
以下代码
QTimer::singleShot(0, qApp, &QCoreApplication::quit)
将使quit()排队并在事件循环开始时执行它。没有其他要求。您可以看一下这个小例子:
#include "mainwindow.h"
#include <QApplication>
#include <QTimer>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
QTimer::singleShot(0, qApp, []() {
qDebug() << "Event loop started";
QCoreApplication::quit();
});
return a.exec(); // QCoreApplication::quit() is executed after the call
}
在事件循环开始之前运行以下代码
qApp->quit() or qApp->exit(1)
不会对您的应用程序产生任何影响。
简历
您似乎没有正确地将代码放置在编辑器中,或者在问题中遗漏了重要部分。我建议您使用上面的代码示例创建一个简单的应用程序。
关于c++ - Qt-从QDialog关闭程序(在MainWindow完全加载之前),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49562236/