[SOLVED] QThread and QTimer
-
Hey,
I'm working on an application developed with Qt 4.6.
I want to create a custom timer that counts in a separate thread. However, I want this timer to be able to send signals to the main thread.
I subclassed QThread but it doesn't seem to work.
Here is Timer.h:
@
#ifndef TIMER_H
#define TIMER_H#include <QtCore/QObject>
#include <QtCore/QThread>
#include <QtCore/QTimer>class Timer : public QThread
{
Q_OBJECT
public:
explicit Timer(QObject *parent = 0);
~Timer();// true if the timer is active bool isCounting(); // start the timer with a number of seconds void startCounting(int value = 300); void stopCounting(); // the number of seconds to reach int maximum(); // the current value of the timer int value(); // elapsed time since the timer has started int elapsedTime();
signals:
// sent when the timer finishes to count
void timeout();
// an event is emited at each second when the timer is active
void top(int remainingSeconds);protected:
// launch the thread
//virtual void run();private slots:
// decrements the remaining time at each second and emits top()
void timerEvent();private:
QTimer* _timer;
// remaining time
int _left;
// number of seconds at timer startup
int _maximum;
};#endif // TIMER_H
@And Timer.cpp:
@
#include "Timer.h"Timer::Timer(QObject *parent) :
QThread(parent)
{
_timer = new QTimer(this);
_maximum = 0;
_left = 0;
connect(_timer, SIGNAL(timeout()), this, SLOT(timerEvent()));
}Timer::~Timer()
{
delete _timer;
}bool Timer::isCounting()
{
return _timer->isActive();
}void Timer::startCounting(int value)
{
qDebug() << QString("Start timer for %1 secs").arg(QString::number(value));
if(_left != 0 || _timer->isActive())
{
_timer->stop();
}_maximum = value; _left = value; emit top(_left); _timer->start(1000); start();
}
void Timer::stopCounting()
{
qDebug() << QString("Stopping timer at %1 secs => %2 secs remaining.").arg(QString::number(elapsedTime()), QString::number(_left));
_timer->stop();
_left = 0;
_maximum = 0;
terminate();
}int Timer::maximum()
{
return _maximum;
}int Timer::value()
{
return _left;
}void Timer::timerEvent()
{
qDebug() << "Timer event";
if(--_left == 0)
{
_timer->stop();
emit timeout();
}
else
{
emit top(_left);
}
}int Timer::elapsedTime()
{
return (_maximum - _left);
}
@ -
Since you subclass QThread and your timer is a member of your subclass, the timer will not be living in the context of the new thread that is managed by your QThread subclass. It will live in the same context as your QThread subclass object, which is the thread the object was created in.
I don't know if this might be related to your problem. But it seemed to me you were not aware of this fact.
Have a look at these links if your not familiar with the new best practise for the use of QThread.
"You're doing it wrong":http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/
"QThreads general usage":http://qt-project.org/wiki/QThreads_general_usage -
Thanks for the links.
I realized I forgot to implement the run() method. It might be the point.However my approach is wrong. I think I will keep the timer in the main thread because it doesn't require heavy resources and I will put my Worker in a thread.
-
You could also make the timer a member of your worker object.
Anyways. Glad I could help. If this solved your problem please mark this thread as solved by editing your first post and prepending "[SOLVED]" to the title.
Edit: BTW the default implementation for QThread::run() just calls exec(). In your case this would suffice.