Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [SOLVED] Correctly exiting from a Qt GUI application with multiple windows/widgets
QtWS25 Last Chance

[SOLVED] Correctly exiting from a Qt GUI application with multiple windows/widgets

Scheduled Pinned Locked Moved General and Desktop
10 Posts 3 Posters 12.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    BDifferent
    wrote on last edited by
    #1

    Hi,
    I have a problem to correctly exit my application.
    There are 2 "modes" in which my application runs, "GUI mode" and cmdline mode. The mode is switched by passing an argument to the application at startup.

    main.cpp:

    @
    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MainWindow w;
    if (argc>1 && strcmp(argv[1], "--nogui") == 0)
    {
    w.hide();
    }
    else
    {
    w.show();
    }
    return a.exec();
    }
    @

    From the MainWindow a second window ("debugPtr" in line 15) is created which is a QWidget containing just a QTextEdit (for debug output).

    In GUI mode everything works as expected - after closing both windows the application exits.
    However, the cmdline mode does not exit properly: cmdline mode is non-interactive, i.e. it conducts some calculations based on settings from a config file and is supposed to quit after that (see mainwindow.cpp, l. 17-22). However, that never happens. It basically "hangs" at the "QApplication::quit()" command. I assumed that it would close all windows of the applications, but it seems it doesn't.
    While investigating this I also tried to make the 2nd window a child of the MainWindow, however that didn't work well, because then the application crashes in the destructor of the MainWindow. Then I commented "delete debugPtr;" in the destructor since it crashed there, also because I understood the documentation in a way that the parent window takes care of deleting its children; but now the destructor crashed in the following line, "delete ui;" so there is something more fundamental going wrong in my approach, I suppose. I am probably misunderstanding someting in the concept of child windows. So I switched back and the 2nd window is now not a child of the MainWindow anymore. Shouldn't it close nevertheless when the application is asked to quit? Is maybe "QApplication::quit()" not the right way? (I think I found it on stackoverflow.com.)

    Note: The 2nd window is created, but not shown, in cmdline mode as well: Within that window's code the output is then done or not done based on the "application mode" in order not to have to check for the application mode at each output of text to this window. This is the reason for creating the window also in cmdline mode.

    Thanks in advance for any suggestions and ideas!

    The rest of the discussed code is:
    (I hope I did not forget any, if so please give me a hint.)

    mainwindow.cpp:

    @MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    QString appArgv = qApp->arguments().last(); // Check if an argument was passed at ap startup.
    isCmdLine = false;
    // if there is more than one argument passed to the app, use the last. If it is "--nogui", then start the application in commandline mode
    if (appArgv == "--nogui")
    {
    isCmdLine = true;
    }

    debugPtr = new DebugDialog(0, isCmdLine); // Create the 2nd window. 0 means no parent, the 2nd argument passes the mode.

    if (isCmdLine == true)
    {
        if (ReplicateRunsAutomatic() == true) // Non-interactive calculations in cmdline mode.
        {
            qDebug() << "Calculations finished successfully. Exiting.";
            QApplication::quit();  // <- Is supposed to exit the application.
        }
    }
    

    else
    {
    // GUI mode stuff
    }
    }

    MainWindow::~MainWindow()
    {
    delete debugPtr;
    delete ui;
    }
    @

    debugdialog.h:

    @class DebugDialog : public QDialog
    {
    Q_OBJECT

    public:
    explicit DebugDialog(QWidget *parent = 0, bool isCmdLine = false);
    ...
    }
    @

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Why not something like that:

      @
      QApplication a(argc, argv);
      if (argc>1 && strcmp(argv[1], "--nogui") == 0)
      {
      MainWindow w;
      w.show();
      return a.exec();
      }
      else
      {
      if (ReplicateRunsAutomatic() == true) // Non-interactive calculations in cmdline mode.
      {
      qDebug() << "Calculations finished successfully. Exiting.";
      return 1;
      }
      return 0;
      }
      @

      Unless your calculations make use of Qt's features, there's no need to start the application. Also it's not the GUI's responsibility to handle that, thus the separation is cleaner.

      Hope it helps

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • B Offline
        B Offline
        BDifferent
        wrote on last edited by
        #3

        I would have to read a bit for which of the Qt libraries that I use I actually need a QApplication. Of course I use Qt classes like QString and also containers like QList; maybe for those I do not need a QApplication (not a Qt expert yet :-) ).
        And for the debug output window I could use a class which contains a QWidget instead of directly inheriting from QWidget. Then the window would only be created in GUI mode but not in cmdline mode and probably a QApplication would be unnecessary. The calls to the debug output would still go to this object but would be filtered out there.

        I will try that, thank you :-)
        Any ideas regarding my parent/children problem?

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          What exact error are you getting ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • A Offline
            A Offline
            ambershark
            wrote on last edited by
            #5

            For command line mode I use QCoreApplication and for gui QApplication.

            The reason it doesn't exit as SGaist said is that you are calling a.exec() at the end. Skip that like he showed you when in command line mode and you should be good.

            So for a simple command line app it would be:

            @
            #include <QCoreApplication>

            int main(int argc, char *argv[])
            {
            QCoreApplication app(argc, argv);

            // do whatever you want here, process arguments, calculate things, etc

            return 0;
            }
            @

            No need to ever go into app.exec() unless you need an event loop. If that was the case you could then call app.quit() somewhere in your CLI processing section. You would need to start whatever you wanted with a QTimer::singleShot() so you could block on the app.exec() but still handle your CLI stuff since there would be no GUI interface.

            Oh and if you are in CLI mode I definitely wouldn't create the widget or a QApplication since those are GUI things. That would make it not a true CLI. It would cause issues if you tried to run it in a headless situation like a linux terminal with no X. It wouldn't start since it would need X windows to create (and then hide) the widget.

            So separate your code into GUI/CLI sections and only create GUI objects in the GUI section.

            My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

            1 Reply Last reply
            0
            • B Offline
              B Offline
              BDifferent
              wrote on last edited by
              #6

              Hi,

              [quote author="SGaist" date="1405724470"]What exact error are you getting ?[/quote]

              I assume you refer to the crash in the destructor? It was a segment violation, and with a debugging build it ended up in a Qt library I think, at least not in my source code. However, I just tried it again (i.e. set the MainWindow as parent of the 2nd window), and it does not crash anymore in the destructor, for whatever reason ... So that problem is "solved" :-)

              I will try to restructure my project in a way that no QApplication is needed in case of cmdline mode so that I can use a QCoreApplication then.

              Thanks for all your help so far!

              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                On a side note, when you create a new widget you should put the parent parameter at the end of the list. Doing so you will follow the standard Qt coding style and it won't hurt your memory muscle when using your widget ;)

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                0
                • B Offline
                  B Offline
                  BDifferent
                  wrote on last edited by
                  #8

                  Will do :-)

                  1 Reply Last reply
                  0
                  • B Offline
                    B Offline
                    BDifferent
                    wrote on last edited by
                    #9

                    I followed your suggestions and now in cmdline mode only a QCoreApplication is created, only for GUI mode a QApplication is created. Works nicely and finishes as expected after the calculations in cmdline mode. At first, in GUI mode the 2nd window didn't close when closing the MainWindow, although I am setting the parent to MainWindow when creating the 2nd window. But after setting the Qt::WA_DeleteOnClose attribute of the window, the window now closes as well when closing the MainWindow.

                    Thanks SGaist and ambershark!

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      ambershark
                      wrote on last edited by
                      #10

                      Nice. Glad you got it all worked out.

                      My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved