Timers
QObject, the base class of all Qt objects, provides the basic timer support in Qt. With QObject::startTimer(), you start a timer with an interval in milliseconds as argument. The function returns a unique integral timer ID. The timer will then fire at regular intervals until you explicitly call QObject::killTimer() with that timer ID.
Instead of handling timer IDs directly, you can use QBasicTimer. QBasicTimer is a value-class, RAII wrapper around a timer ID. You start the timer with QBasicTimer::start(), and stop it with QBasicTimer::stop() (the latter is also called upon destruction). To use QBasicTimer, you must reimplement timerEvent() in your class (which must be a sub-class of QObject), and handle the timer event there.
For this mechanism to work, the application must run in an event loop. You cat start an event loop with QApplication::exec(). When a timer fires, the application sends a QTimerEvent, and the flow of control leaves the event loop until the timer event is processed. This implies that a timer cannot fire while your application is busy doing something else. In other words: the accuracy of timers depends on the granularity of your application.
In multithreaded applications, you can use the timer mechanism in any thread that has an event loop. To start an event loop from a non-GUI thread, use QThread::exec(). Qt uses the object's thread affinity to determine which thread will deliver the QTimerEvent. Because of this, you must start and stop all timers in the object's thread; it is not possible to start timers for objects in another thread.
The main API for the timer functionality is QTimer. QTimer stores the interval in a signed integer, which limits the maximum interval it supports to the number of milliseconds that can fit in a signed integer (in practice, this is a period of around 24 days).
Qt 6.8 introduced the QChronoTimer class. The main difference between the two classes is that QChronoTimer supports a larger interval range and a higher precision (std::chrono::nanoseconds
). For QTimer the maximum supported interval is ±24 days, whereas for QChronoTimer it is ±292 years. If you only need millisecond resolution and ±24 days range, you can continue to use QTimer.
The accuracy of the timers depends on the underlying operating system. Windows 2000 has 15ms accuracy; other systems that we have tested can handle 1ms intervals.
QChronoTimer provides regular timers that emit a signal when the timer fires, and inherits from QObject so that it fits well into the ownership structure of most Qt programs. The normal way of using it is like this:
QChronoTimer *timer = new QChronoTimer(1s, this); connect(timer, &QChronoTimer::timeout, this, &MyWidget::processOneThing); timer->start(); QChronoTimer *timer = new QChronoTimer(this); connect(timer, &QChronoTimer::timeout, this, &MyWidget::processOneThing); timer->setInterval(1s); timer->start();
The QChronoTimer object is made into a child of the this
object so that, when this
is destroyed, the timer is destroyed too. Next, the timeout() signal is connected to the slot that will do the work, the timer interval can be either passed to the constructor, or set later on with setInterval().
QChronoTimer also provides static functions for single-shot timers. For example:
MyWidget widget; QChronoTimer::singleShot(200ms, &widget, &MyWidget::updateCaption);
200ms after this line of code is executed, the updateCaption()
slot will be called.
For QChronoTimer to work, you must have an event loop in your application; that is, you must call QCoreApplication::exec() somewhere. Timer events will be delivered only while the event loop is running.
In multithreaded applications, you can use QChronoTimer in any thread that has an event loop. To start an event loop from a non-GUI thread, use QThread::exec(). Qt uses the timer's thread affinity to determine which thread will emit the timeout() signal. Because of this, you must start and stop the timer in its thread; it is not possible to start a timer from another thread.
The Analog Clock example shows how to use QChronoTimer to redraw a widget at regular intervals. From AnalogClock
's implementation:
AnalogClock::AnalogClock(QWidget *parent) : QWidget(parent) { auto *timer = new QChronoTimer(1s, this); connect(timer, &QTimer::timeout, this, QOverload<>::of(&AnalogClock::update)); timer->start(); ... ... setWindowTitle(tr("Analog Clock")); resize(200, 200); }
Every second, QChronoTimer will call the QWidget::update() slot to refresh the clock's display.