Why is event loop left



  • I want to write a small program doing the following:

    • start a single-shot QTimer
    • when it times out, a QMessageBox is shown
    • if button "Continue" is clicked, the box is closed and the timer is restarted
    • if button "Stop" is clicked, the box is closed and the application is exited

    The problem I have is that the event loop is left as soon as I hide the message box. The box is displayed only once. I reproduced my program in a console version, that I can provide here on demand, and it runs as expected. Here is my code. Thanks in advance for your help.

    main.c

    #include <QtGui/QApplication>
    #include "TimedDialog.h"
    
    int main(int argc, char *argv[])
    {
      QApplication app(argc, argv);
    
      TimedDialog dialog(&app, SLOT(quit()));
      dialog.run();
    
      return app.exec();
    }
    

    TimedDialog.h

    #ifndef TIMED_DIALOG_H
    #define TIMED_DIALOG_H
    
    #include <QObject>
    #include <QTimer>
    
    class QMessageBox;
    class QPushButton;
    class QAbstractButton;
    
    class TimedDialog : public QObject
    {
      Q_OBJECT
    
    public:
      TimedDialog(
        QObject const * receiver,
        char const * method);
    
      ~TimedDialog();
    
      void run(void);
    
    signals:
      void stop(void);
    
    private:
      QMessageBox* _box;
      QPushButton* _buttonContinue;
      QPushButton* _buttonStop;
      QTimer _timer;
    
      static int const DELAY = 2 * 1000; // [ms]
    
    private slots:
      void onTimeout(void);
      void onButtonClicked(QAbstractButton * button);
    };
    
    #endif
    

    TimedDialog.cpp

    #include <assert.h>
    #include <QMessageBox>
    #include <QPushButton>
    
    #include "TimedDialog.h"
    
    TimedDialog::TimedDialog(
      QObject const * receiver,
      char const * method)
      : QObject(),
      _box(0),
      _buttonContinue(0),
      _buttonStop(0),
      _timer()
    {
      _box = new QMessageBox();
      _box->setWindowModality(Qt::NonModal);
      _box->setText("Here is my message!");
    
      _buttonContinue = new QPushButton("Continue");
      _box->addButton(_buttonContinue, QMessageBox::AcceptRole);
    
      _buttonStop = new QPushButton("Stop");
      _box->addButton(_buttonStop, QMessageBox::RejectRole);
    
      _timer.setSingleShot(true);
    
      assert(connect(&_timer, SIGNAL(timeout()), this, SLOT(onTimeout())));
      assert(connect(_box, SIGNAL(buttonClicked(QAbstractButton *)), this, SLOT(onButtonClicked(QAbstractButton *))));
      assert(connect(this, SIGNAL(stop()), receiver, method));
    }
    
    TimedDialog::~TimedDialog()
    {
      delete _box;
    }
    
    void TimedDialog::onTimeout(void)
    {
      _box->show();
    }
    
    void TimedDialog::onButtonClicked(QAbstractButton * button)
    {
      _box->hide();
    
      if (button == _buttonContinue)
      {
        _timer.start(DELAY);
      }
      else
      {
        emit stop();
      }
    }
    
    void TimedDialog::run(void)
    {
      _timer.start(DELAY);
    }
    

  • Qt Champions 2016

    Hi
    Pr default the application will exit event loop when no more windows open.
    Which is your case right from beginning :)

    You can turn this off
    http://doc.qt.io/qt-5/qguiapplication.html#quitOnLastWindowClosed-prop

    and then call quit() your self when Stop is clicked.



  • Thanks for your reply, mrjj
    It solves my problem and contributes to extend my learning of Qt! I thought the event loop is left when there is no more event programmed, like my timeout().
    But what do you think now about my console version here below? There is no window at stake and the event loop is not left !? Is it explained by a difference between QApplication and QCoreApplication?

    main.c

    
    #include <QtCore/QCoreApplication>
    #include "MyTimer.h"
    
    int main(int argc, char *argv[])
    {
      QCoreApplication app(argc, argv);
    
      MyTimer myTimer(&app, SLOT(quit()));
      myTimer.start();
    
      return app.exec();
    }
    

    MyTimer.h

    #include <QObject>
    #include <QTimer>
    
    class MyTimer : public QObject
    {
      Q_OBJECT
    
    public:
      MyTimer(QObject const * receiver, char const * method);
      ~MyTimer();
    
      void start(void);
    
    signals:
      void stop(void);
    
    private:
      QTimer _timer;
    
    private slots:
      void onTimeout(void);
    };
    

    MyTimer.cpp

    #include "MyTimer.h"
    #include <iostream>
    #include <assert.h>
    
    MyTimer::MyTimer(QObject const * receiver, char const * method)
      : QObject(),
      _timer()
    {
      _timer.setSingleShot(true);
      assert(connect(&_timer, SIGNAL(timeout(void)), this, SLOT(onTimeout(void))));
      assert(connect(this, SIGNAL(stop()), receiver, method));
    }
    
    MyTimer::~MyTimer(void)
    {
    
    }
    
    void MyTimer::start(void)
    {
      _timer.start(2000);
    }
    
    void MyTimer::onTimeout(void)
    {
      std::cout << "Continue ? ";
      char response('n');
      std::cin >> response;
    
      if (response == 'n')
      {
        emit stop();
      }
      else
      {
        _timer.start(2000);
      }
    }
    

  • Qt Champions 2016

    Hi
    Yes - it explained by a difference between QApplication and QCoreApplication?

    QCoreApplication expects you to call quit. QApplication can auto close on
    last top level window close.

    So return app.exec(); does work differently between Core and Application.

    Both does exit on quit().

    It cant wait for "last event" as impossible to know if last timer event seen, will be the last etc.



  • OK. Thanks for all.
    Kind regards.


Log in to reply
 

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