You have probably used the QTimer class for basic timing operations in Qt. Common use cases include polling for events (not always a good approach, but sometimes necessary), updating the user interface or performing some other function at regular intervals. And you probably know about the repetitive and single-shot modes of QTimer timers.
In this blog post we'll look at some of the other timer classes provided by Qt that you may not be familiar with if you've only use a simple QTimer.
Before doing that, I'd like to point out a feature of QTimer you may not be aware of. Through the timerType property, three different types of timers are supported: PreciseTimer, CoarseTimer, and VeryCoarseTimer. Each type offers different tradeoffs between accuracy and precision, overhead, and ease of use. You can read the details in the Qt documentation.
I should also mention that an alternative to using timers can be delays. While a busy wait is a well-known anti-pattern, if can be appropriate in some cases, although usually not in an application's main or UI thread. Qt provides portable versions of a number of delay functions: msleep, qSleep, sleep, and usleep. Similar delay functions are part of the C++ standard library (for example, sleep_for and sleep_until), and the POSIX standard which most operating systems provide some level of conformance to.
The QBasicTimer class provides timer events for Qt objects. Compared to QTimer, it is a fast, lightweight, low-level class that is used internally by Qt.
To use the class you create a QBasicTimer instance. The timer is started by calling its start() method specifying the timer repetition rate, timer type, and a QObject-derived object to receive the timer events.
When the timer times out, it sends a timer event to the object. It is a repetitive timer that will send timer events until its stop() method is called.
I wrote a small example application that illustrates the use of a QBasicTimer. You can download the entire project here.
You can set the timer type from a combo box and start the timer by pressing the Start button. The elapsed time is shown on an LCD display widget. While the timer is running, the Start buttons changes to Stop so you can stop the timer. a Clear button will reset the time to zero. A screen shot is shown below:
Feel free to examine the code at your leisure. In the main window's constructor we create a timer instance:
When the Start button is pressed and the timer is stopped, we call start() specifying the timer rate (100 ms), timer type (taken from a combobox in the UI), and set the main window as the object to receive the timer events.
Timer events are received in the timerEvent method implemented in the class. We increment the timer count and update the LCD display. The event is also accepted, although that is not strictly necessary:
ui→lcdNumber→display(count / 10.0);
You can experiment with the different timer types and see if the behavior changes. In most cases, including this application, it is usually more convenient to use a QTimer and connect its timeout() signal to a slot.
For applications where you want the reduced overhead of a QBasicTimer (maybe one with many timers), QBasicTimer can be a good choice.
Another timer class provided by Qt is QElapsedTimer. It is typically used to calculate the elapsed time between two events. The common use case is to create a QElapsedTimer instance and call its start() method before performing a slow operation. Then, after the operation completes, calling the timer's elapsed() method will return the elapsed time in milliseconds. It provides a number of useful methods including returning the time remaining before a time period or whether a certain amount of time has elapsed.
Common applications for QElapsedTimer include calculating the time of an operation and supporting a timeout if an operation takes too long to complete. I wrote a QElapsedTimer example that illustrates some of the features of this timer type. A screen shot is shown below and the source code can be downloaded from here.
The application allows you to select one of four operations, a floating point multiplication, division, sine, or cosine calculation, or no operation at all. You can also select how many times the operation will be performed. Clicking on the Start button will perform the operation the selected number of times, and then display information about how long it took.
The code is meant to illustrate how to use a QElapsedTimer and is not necessarily the best way to accurately measure these operations. In this case the timing is probably dominated by the random number generator function and not the actual operation being performed on the numbers.
Included in the code is an example of using the hasExpired() method to determine if a specific amount of time has passed. In the case of the multiply operation, it stops the operation if more than one second has elapsed.
Feel free to examine the code, and to test your understanding of QElapsedTimer by making some changes. If you are familiar with C++11 or later, a possible enhancement would be to use C++ lambda functions to perform the operations.
QDeadLineTimer is a class similar to QElapsedTimer, but is more convenient for calculating whether a specific future time has expired.
I didn't create an example application for this classes. It should be straightforward to modify the QElaspedTimer example to use this class instead. For example, you could have the selected operation run repeatedly until a specified amount of time has passed.
Other Related Classes
Qt has some other classes related to timers and timing. The QTimerEvent class contains parameters that describe a timer event. In the QBasicTimer example program, the data passed to the timerEvent() handler was a QTimerEvent object.
QMediaTimeRange is part of the multimedia module and is used to represent time ranges.
The QOpenGLTimerQuery class wraps an OpenGL timer query object.
In the QML world, Qt provides the Timer QML type. It provides similar functionality to the QTimer C++ class, offering repetitive or single shot timers that emit a signal at a specified rate.
Here is a standalone QML program that implements similar functionality to the QBasicTimer example: a stopwatch application. It can be run from the qmlscene program. Here is the complete source code:
import QtQuick 2.6
import QtQuick.Controls 2.4
property int count: 0
onTriggered: count += 1
text: (count / 10).toFixed(1)
text: timer.running ? "Stop" : "Start"
onClicked: timer.running = !timer.running
onClicked: count = 0
And here is a screen shot of the application running:
I think you can now appreciate that Qt provides an extensive set of C++ classes to meet just about any need related to timing, as well as a QML Timer type. I should also mention that the C++ standard library also offers clock and timer functions, which can be a viable approach depending on your requirements.
Want more Qt content? We've got you covered.