Qt - 从QDialog关闭程序(在MainWindow完全加载之前)

时间:2018-03-29 17:45:13

标签: c++ qt

引言

您好。在我的应用程序中,我在MainWindow的构造函数完成之前运行QDialog。根据此QDialog中的用户输入,我想关闭应用程序。

问题

我无法调用qApp->quit()qApp->exit(int retcode = 0),因为QApplication事件循环尚未启动。有没有办法可以强制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 show。它确实有效。我进一步前进了一步,并使用了本节中其他程序的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 ONLY 重新实施拒绝方法。它仍然没有奏效。第一次调用拒绝时,它经历了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"

2 个答案:

答案 0 :(得分:2)

#include <QShowEvent>
#include <QDebug>
...
protected:
    ...
    void showEvent(QShowEvent *event);
    ...
private:
    ...
    bool init_check = false;
    ...


void MainWindow::showEvent(QShowEvent *event){
    qDebug() << "QShowEvent" << init_check;

    if(!init_check){
        init_check = true;
        bool err = true;
        if(err){
            qDebug() << "Closing app";
            exit(EXIT_FAILURE);
        }
    }
}

答案 1 :(得分:2)

以下代码

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) 

对您的申请不会有任何影响。

<强> 恢复

您似乎没有在编辑器中正确放置代码,或者您在问题中遗漏了重要部分。我建议您使用上面的代码示例创建一个简单的应用程序。