[SOLVED] Wait on Timer
-
Hey there
I have an application that starts a QTimer in the MainWindow-destructor. Now, my problem is, that the destructor just starts the timer and then quits the application. How can I realize this, that the destructor needs to wait until the timer is stopped and just then quits the application?
Thx for help
-
Is there work which has to be done while waiting?
If not "QThread::sleep()":http://doc.qt.nokia.com/latest/qthread.html#sleep will do the trick.
If yes i would suggest to rearrange your program flow so that the destructor isn't called at all before the work hasn't been finished. -
The timer shuts down an extern hardware component which is controled with a serial port and therefore I need the timer as frequency generator. As soon as the component is off, the timer stops and then the application would be ready to quit.
It is not a question of finishing the work, but if someone forgets to shut down the hardware component before quitting the application, I need an protection that the application makes this on it's own.
-
@
QTimer t;
t.start(3000);QEventLoop loop;
connect(&t, SIGNAL(timeout()), &loop, SLOT(quit()));
loop.exec();
@This starts the timer, creates an event loops, keeps that loop spinning. Once the timer timeouts, it sends signal timeout which quits the event loop and the flow of control continues.
-
[quote author="luggi" date="1308127054"]The timer shuts down an extern hardware component which is controled with a serial port and therefore I need the timer as frequency generator. As soon as the component is off, the timer stops and then the application would be ready to quit.
It is not a question of finishing the work, but if someone forgets to shut down the hardware component before quitting the application, I need an protection that the application makes this on it's own.[/quote]
This all should be done before exiting the event loop (ie. calling quit() or exit() or destructing the application object), because without a running event loop (exec() has returned) there won't be any timer functionality anymore.
EDIT: Added quote for clarification.
-
Is it possible to just override the closeEvent method in QWidget?
-
Thx, but as I need the timer as frequency generator, the timeout is already reserved for every frequency impulse. How can I connect this loop with the "isActive()" Method? This would be the best solution, something like:
@
if( QTimer->isActive() )
{
"Do the loop which is connected to the timer";
}
else
{
"Quit application";
}@@mario: Is there also a closeApplication Eventhandler, because I have several windows.
-
There is no such event as far as I know. There is a QCoreApplication::aboutToQuit() signal which is called as soon as your application is - well - about to quit. But you will face to same problem as with your destructor solution as your application - and so your event loop - is about to quit.
I would suggest reimplementing the closeEvent of your main window, discard it in case the device is still up and running and trigger your shutdown code. As soon as your device is shut down you can quit your application using QCoreApplication::quit().
Take care of keeping you event handler code short (in terms of time) because your event loop is (and so are your timer signals) blocked.
-
Hmm okay, I found a possibility. It's not that proper but it has even a little advantage.
First thing in the destructor is to start the timer which results in any loop. Secondly I execute a QMessageBox without buttons. As long as this messagebox exists, the programm isn't quitting and my other loop does its work in the background.
Finally I invoke the messagebox to be done at the end of my necessary loop. And as the messagebox is gone, the application quits.
The advantage is, that I'm able to tell the user what's happening at the moment, so that he don't gets crabby becaus the application don't quits directly.
@
MainWindow::~MainWindow()
{
anyTimer.start(int);
quitMessageBox.setText("Don't get crabby, I'm still doing something!");
quitMessageBox.setStandardButtons(QMessageBox::NoButton);
quitMessageBox.exec();
}
@At the end of the loop.
@
quitMessageBox.done(0);
@ -
Re-think your design a bit.
Why is the code to interact with hardware in a class that is responsible for the GUI? It would make more sense to have a class dedicated to interacting with your hardware, I think. That means that your main window would no longer be responsible for the proper shutdown of your hardware, but the specialist class. That may seem like a small change, but it isn't. It means that you can close and destruct your UI and let the destructors there do what they are meant to do. And no, waiting on a timer isn't a good idea to do in a destructor. Then, even if the main window is closed, you simply don't quit the application before the hardware manager class tells you it is ok to quit the actual application. -
Now I'm a bit confused. Well I have to say, that this is my first in some degree complex application I make with Qt. So as I understand you correctly, I should just insert my UI elements in the mainwindow and the rest directly in the main-file? Because now, I wrote the whole application in the mainwindow. The main-file just creats a mainwindow and shows this.
To the destructor. There are two possibilities to quit the application. First by closing the window, secondly by using the quit-action in the menubar. Finally I need the application to do some work before quitting. As I integrated the whole application in the mainwindow there is only one possibility when the destructor of the mainwindow is called, that is when the application quits anyway.
Could you give me a quick overview of a proper structure with UI and e.g. a class which comminicates with a serial port?
-
No, who it talking about putting this directly in your main file?
But indeed, you can have more objects that constitute your application than just your main window. Your MainWindow is just a window. Why let it be responsible for every single aspect of your application? What I regulary do, is create some kind of Controller object, that basically binds together different parts of the application: the UI, objects that perform actual work, etc. It is the controller who tells the QApplication instance it can quit, not the window.
On your assessment that there are two ways an application can quit: that is wrong. Closing a window or using the quit menu item is from a users perspective the way to quit an application, but nobody forces you to hook up those events directly to the quit() method of your QApplication. Instead, you can use these to trigger a code path in your application that will eventually lead to the application quitting, but only if it is ready to do so.
-
That's right. So I have the possibility to execute another class instead of quitting the application. And if this class is done with it's work, it quits the application. Unfortunately I don't need just to shutdown the hardware at the end of the application. It is also possible to shut down the hardware during the application.
That means that I have to set up the class with a flag. If the flag is on, quit the application at the end, if not, just shut down the hardware. Am I right like this?
-
No, probably not. You just need to have your controller object be aware that if the application should shut down, it should do that only after the hardware is ready to be shut down. Again: don't give classes tasks that are not related to what they need to do. If a class manages a piece of hardware, then that is what it does. Don't give it the responsibility to shutdown your application as well.
-
Okay, so if the user wants to quit the application, then it's the controller which tells the hardware-class I want to quit the app so start to shutdown the hardware. Then if the hardware-class is finished with it's work, it tells to the controller I'm done and finally the controller quits the application?