简体   繁体   中英

Qt - Closing the program from a QDialog (Before MainWindow fully loaded)

INTRODUCTION

Hi. In my application, I run a QDialog before the constructor of the MainWindow finishes. Depending on the user input in this QDialog, I want to close the application.

THE PROBLEM

I can't call qApp->quit() or qApp->exit(int retcode = 0) as the QApplication event loop haven't started. Is there a way I can force MainWindow to quit? Or maybe wait until it is fully loaded before quitting?

SOLUTIONS?

I managed to make it work but I have no idea why. This is the .cpp of my QDialog at the moment:

    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);
    }

Using QTimer::singleShot(0, qApp, &QCoreApplication::quit) , QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection) , qApp->quit() or qApp->exit(1) did nothing.

But, for some reason, using ( qApp->quit() or qApp->exit(1) ) and ( QTimer::singleShot(0, qApp, &QCoreApplication::quit) or QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection) ) works!

I feel that using this solution can come back to bite me in the ass later, since I don't know how it is working. Does anyone have a better solution or an explanation?

EDIT

Calling QTimer::singleShot(0, qApp, &QCoreApplication::quit) alone is not closing the application for me. Although, the second time I pass through the function, it does close. The QTimer::singleShot() is on a re implemented QDialog::reject method. And, before closing I show a QMessageBox . Any of this can interfere with the QTimer ?

EDIT 2

I ran the example @user3606329 show. It does indeed work. I went a few steps further and used my QDialog from the other program in this one. And it indeed did not work. So the problem is in my QDialog ? Below is the entire reject method:

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);
    }
}

EDIT 3

I decided to create another QDialog and ONLY re implement the reject method with QTimer::singleShot . It still didn't work. The first time reject was called, it went through QTimer::singleShot and did nothing (Not even closed the Dialog). The second time, it closed the dialog and closed the application. Any ideas why? (Code below)

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();
}

Output:

QTimer done //first click on "close window"
Event loop started //first click on "close window"
QTimer done //second click on "close window"
#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);
        }
    }
}

The following code

QTimer::singleShot(0, qApp, &QCoreApplication::quit) 

will queue quit() and execute it when the event loop is started. Nothing else is required. You can take a look at this small example:

#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
}

Running the following code before the event loop starts

qApp->quit() or qApp->exit(1) 

will not have any effect to your application.

Résumé

It appears that you have either not placed the the code correctly in your editor or you left out important parts in your question. I suggest you create a simple application with my above code example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM