Qtimer Signal Slot Example
The QTimer class provides a high-level programming interface for timers. To use it, create a QTimer, connect its timeout signal to the appropriate slots, and call start. From then on, it will emit the timeout signal at constant intervals. Example for a one second (1000 millisecond) timer (from the Analog Clock example). QTimer example for PyQt5 If an operation is performed periodically in the application, such as periodically detecting the CPU value of the host, then the QTimer timer is needed. When the window’s control receives a Timeout signal, it stops this timer. QTimer has the method start (milliseconds) and Stop.
Our app's UI is finished, so now we'll create a timer and implement our countdown.
The QTimer class provides a high-level programming interface for timers. To use it, create a QTimer, connect its timeout signal to the appropriate slots, and call start. From then on it will emit the timeout signal at constant intervals. Example for a one second (1000 millisecond) timer (from the Analog Clock example). Next, its timeout signal is connected to the slot that will do the work, it is started with a value of 1000 milliseconds, indicating that it will time out every second. QTimer also provides a static function for single-shot timers. For example: QTimer:: singleShot(200, this, SLOT(updateCaption)). This is an example audio/video player using QtGStreamer. In this example, the GStreamer playbin2 element is used to perform most of the tasks. Our code is mostly integrating the UI with the pipeline, handling state changes, doing queries to learn about the position and duration of the stream, performing seeking, etc.
Using the QTimer class
Let's take a minute to review the behavior that we defined for our finished app. The app has a button that, when clicked, changes the traffic signal from red to green. The button also starts a countdown timer, which is indicated visually in the text area of the UI. When the timer reaches 0, the traffic light changes to yellow, pauses briefly, and then changes to red.
We need a way to keep track of how much time is left before the traffic light should change to yellow. Fortunately, the Qt framework includes a class called QTimer that we can use to do just that. You can set a timer interval for a QTimer object and a signal, timeout(), will be emitted at that interval. For example, if you set an interval of 2000 milliseconds, the QTimer object emits its timeout() signal every two seconds while the timer is active. You can call start() to start the timer, and stop() to stop it.
We can use the functionality of QTimer in our traffic light app. We can use one QTimer object, with an interval of one second, to keep track of the countdown until the traffic light should turn yellow. When this QTimer emits its timeout() signal, we update the text in the countdown TextArea. We can use a second QTimer object, with an interval of about two seconds, to pause the traffic light in the yellow state before changing to the red state.
There's a problem with this plan, though: we can't use the QTimer class (and other Qt and C++ classes) in QML automatically. We need a way to provide access to the features of QTimer directly from QML. There are several ways to do this, but here are two possible approaches that we could choose to use in our app:
- Use the attachedObjects list in a QML control to specify the C++ objects that you want to use (in this case, QTimer).
- Create a class that extends the CustomControl class, and provide access to an underlying QTimer object. Then, register this new class for use in QML.
To demonstrate more Cascades features in this tutorial, we'll use the second approach for our traffic light app. One of the benefits of extending CustomControl is the ability to create a visual representation for the new control. Because CustomControl inherits from Control (which itself inherits from VisualNode), you can use the properties of these inherited classes to define how your control looks (for example, preferredWidth, opacity, scaleX, and so on). For the purposes of this tutorial, we won't create a visual representation for the timer that we make, but we'll leave that as an optional extension to our app.
Create the header file for the Timer class
To declare our class elements, create a C++ header file called timer.hpp in the src folder of the project (right-click the src folder and click New > Header File). In this file, keep the pre-populated code, and in between the #define and #endif statements, add the appropriate #include statements. We need to include both QObject and CustomControl. We also need to use a forward declaration of the QTimer class:
Next, we create the Timer class, extending CustomControl. We also use the Q_OBJECT macro to indicate that this class should be preprocessed by the Meta-Object Compiler (moc) tool to compile correctly. For more information about the moc tool in Qt, see Using the Meta-Object Compiler (moc) on the Qt website.
The QTimer class includes a couple of properties that we want to expose in our own Timer class. The active property indicates whether the timer is running, and the interval property specifies the current interval that the timeout() signals are emitted at. We expose these properties by using the Q_PROPERTY macro, and we use the READ and WRITE keywords inside this macro to specify functions that access and change each property. The NOTIFY keyword is also important, and specifies the signal that's emitted when the property changes. For more information about properties in Qt and the Q_PROPERTY macro, see The Property System on the Qt website.
We now declare the public functions of the Timer class, including the constructor. We need functions to get and set the interval of the timer, and we should also have a way to access the state of the timer (active or inactive):
This class includes two slots, start() and stop(), to start and stop the timer. Remember that slots are normal member functions, but are declared in a public slots: section so that they can be connected to signals if needed:
Our class also includes three signals: timeout(), intervalChanged(), and activeChanged(). These signals are emitted in the definitions of our class functions, which we'll add soon when we create our timer.cpp file. We declare our signals in a signals: section:
Finally, we declare the underlying QTimer object that our Timer class uses:
Create the source for the Timer class
To define our class elements, create a C++ source file called timer.cpp in the src folder of the project (right-click the src folder and click New > Source File). This source file doesn't include any pre-populated code, so we start by adding the appropriate #include statements. We need to include QTimer, as well as timer.hpp that we created:
Next, we create the constructor for Timer. The constructor creates a QTimer object to represent our timer. We also call QObject::connect() to connect the timeout() signal in QTimer to the timeout()signal of our Timer class. This way, when the QTimer emits the timeout() signal, our timer also emits its timeout() signal and we can handle it using a signal handler in QML. We use the setVisible() function to indicate that our timer shouldn't be visible on the screen, because it has no visual representation defined for it. The constructor also includes a Q_UNUSED macro, which simply means that the parent parameter isn't used in the body of the constructor.
The isActive() function just returns the value of the active property by calling isActive() of the underlying QTimer object. Similarly, the interval() function calls interval() of the QTimer object to return the interval of the timer:
The setInterval() function calls setInterval() of QTimer to set the interval of the timer, and also emits the intervalChanged() signal by using the emit keyword:
The last functions to implement are start() and stop(). These functions call the corresponding functions of the underlying QTimer object. They also emit the activeChanged() signal:
Our Timer class is now ready for us to use.
Hi,
I cannot figure out how moveToThread is working with QTimer class member.
I have a simple code example of my problem.
Description of the code example:
MyObject1:
Create MyObject2.
Move MyObject2 to a thread using moveToThread.
Connect the started signal from QThread to the MyObject1 slot process.
MyObject2:
Class that inherits from QObject.
Contain a QTimer member.
Contain a process slot.
Running behavior:
In the process slot of MyObject2 I start my QTimer class member and I get:
@QObject::startTimer: timers cannot be started from another thread@
Resolve the problem:
I can get rid of this, by defining my QTimer member as a pointer and create it in the process slot.
Question:
What I do not understand is why in the case that my QTimer class member is not a pointer, my timer is running in a different thread?
moveToThread should make it running in the same thread as MyObject2 thread, no?
Code example:
@#include <QDebug>
#include <QThread>
#include 'mythread1.h'
#include 'mythread2.h'
MyObject1::MyObject1(QObject *parent) :
QObject(parent)
{
qDebug() << 'Constructor object1, THREAD :' << QThread::currentThreadId();
}
#ifndef MYTHREAD1_H
#define MYTHREAD1_H
#include 'mythread2.h'
class MyObject1 : public QObject
{
Q_OBJECT
public:
explicit MyObject1(QObject *parent = 0);
signals:
public slots:
protected:
private:
};
#endif // MYTHREAD1_H
#include <QDebug>
#include <QThread>
#include 'mythread2.h'
MyObject2::MyObject2(QObject *parent) :
QObject(parent)
{
qDebug() << 'Constructor object2, THREAD :' << QThread::currentThreadId();
}
void MyObject2::process()
{
qDebug() << 'Object2' << func << 'THREAD :' << QThread::currentThreadId();
m_timer.setInterval(5000);
connect (&m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
m_timer.start();
}
void MyObject2::onTimeout()
{
qDebug() << func << 'Object2 THREAD :' << QThread::currentThreadId();
}
#ifndef MYTHREAD2_H
#define MYTHREAD2_H
Qtimer Timeout
#include <QTimer>
class MyObject2 : public QObject
{
Q_OBJECT
public:
explicit MyObject2(QObject *parent = 0);
signals:
Qt5 Qtimer
public slots:
void process(void);
void onTimeout(void);
protected:
};
#endif // MYTHREAD2_H@
Qtimer Signal Slot Examples
Thanks in advance for your help.
Qtimer Start
Julien.