[SOLVED] QApplication not finishing after MainWindow closed



  • Hi everybody!

    I just had a problem that I managed to solve, but I still don't understand why it was not working.
    I need to perform some checks in my class constructor, and if one fails, the application should finish. First I tried to call close() in the constructor, but it not worked because the event loop had not started (as far I understand), and anyway I call show() after in main.cpp. Then I tried to perform the tests before calling show() but, although the MainWindow is never shown, the application does not end. I also tried to call show() first and then call the test function (from main.cpp), but my application never ends (although the window is closed).

    I attach some parts of the code:

    @void ArmyEditor::initialize() {
    // This function makes sure an Army File is opened/created before we can work with the MainWindow

    StartDialog dialog(this); // Just a class that inherits from QDialog
    QFileDialog fileDialog(this, tr("Select Game File"), QString(), tr("yALB Game File (*.ygf)"));
    fileDialog.setFileMode(QFileDialog::ExistingFile);
    bool getAction = true;
    
    
    while(getAction) {
        if(dialog.exec() == StartDialog::Accepted) {
            if(dialog.getResult() == StartDialog::CreateFile) {
                if(fileDialog.exec() == QFileDialog::Accepted) {
                    QString gameFile = fileDialog.selectedFiles().at(0);
                    if(gameFile.isEmpty() == false && newArmyFile(gameFile)) {
                        getAction = false;
                        break;
                    }
                }
            } else {
                if(fileDialog.exec() == QFileDialog::Accepted) {
                    QString gameFile = fileDialog.selectedFiles().at(0);
                    fileDialog.setFilter(tr("yALB Army File (*.yaf)"));
                    if(gameFile.isEmpty() == false && fileDialog.exec() == QFileDialog::Accepted) {
                        QString armyFile = fileDialog.selectedFiles().at(0);
                        if(armyFile.isEmpty() == false && openArmyFile(armyFile, gameFile)) {
                            getAction = false;
                        } else
                            fileDialog.setFilter(tr("yALB Game File (*.ygf)"));
                    }
                }
            }
        } else {
            // User clicked exited from Start Dialog, finish app
            this->close();
            return;
        }
    }
    

    }@

    @#include <QtGui/QApplication>
    #include "armyeditor.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    ArmyEditor w;
    w.show();
    w.initialize();

    return a.exec&#40;&#41;;
    

    }
    @

    I managed to solve it by declaring initialize() as a slot and adding this line at the end of ArmyEditor's constructor:
    @QTimer::singleShot(0, this, SLOT(initialize()));@

    I understand the previous line calls the slot when the event loop starts, but the same should happen in the first case, shouldn't it?

    Thanks and greetings!



  • I believe it is wrong to do anything but loading the widgets you'll use before you call exec(), since the events won't be processed and something might lock your widget "opened" (which may be the reason your program is not closing).


  • Moderators

    Instead of calling "this->close()" in your class, do it like that:
    @
    qApp->quit();
    @

    This will tell the global application object to finish.

    You could also move "w.initialize();" before "w.show();".



  • Thanks for the replies..

    @veeeee_d: But if I call exec() then the next line (w.initialize()) won't be called until the MainWindow is closed.

    @sierdzio: I had already tried with qApp->quit(), but it does not even close the MainWindow. I tried writing w.initialize() before w.show() also.

    Thanks again!


  • Moderators

    I am wondering why you are not having a return value for your initialisation method?
    If you want to use it as a slot, this is certainly a reason, but so far, it looks like to want to call it only once and even prior to exec(). If the routine would return a bool, you can mark with a false, that something is definitely wrong. This allows you to exit immediately the main part prior to calling show() and exec().



  • Thanks for your answer.

    Yes, I was using like that before.. I had something like this:

    @#include <QtGui/QApplication>
    #include "armyeditor.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    ArmyEditor w;
    if(w.initialize())
    w.show();

    return a.exec&#40;&#41;;
    

    }@

    Should I call a.exec() only when w.initialize() is true?

    Thanks!


  • Moderators

    I would do like this:

    @#include <QtGui/QApplication>
    #include "armyeditor.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    ArmyEditor w;
    if(!w.initialize())
    return 10; // choose a return value you like

    w.show();
    
    return a.exec(&#41;;
    

    }@

    This assumes certainly that it does not make sense to continue the execution with such a failure in initialization. I do not see a reason to start the exec loop for nothing.



  • Yes, it works.. Anyway, I still don't understand why it was not working.. Shouldn't the exec loop finish automatically if there are no windows opened? Maybe the app never recieves the "message" to close, but doesn't the fact that close() effectively closes the MainWindow means that the event loop has started?

    Thanks!


  • Moderators

    exec method is not part of "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html but of "QCoreApplication":http://doc.qt.nokia.com/4.7/qcoreapplication.html The latter one is for console applications without windows. So, it cannot rely on windows to be open and closed.

    [Edit] I have just noticed that exec() may be different for QApplication and QCoreApplication since it is listed in the documentation for both. Since it is a static method it is listed in a different section.



  • Thanks! I will mark this as solved.

    For this application I will use QTimer::singleShot(0, this, SLOT(initialize())); because I want the MainWindow is visible before I show StartDialog, but I will take your suggestion for another application of my package that need to perform this tests before anything is shown.

    Thanks again!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.