Solved 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); }
-
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-propand 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); } }
-
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.