c++ - QThread and QTimer -
i'm working on application developed qt 4.6.
i want create custom timer counts in separate thread. however, want timer able send signals main thread.
i subclassed qthread doesn't seem work.
here 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 timer active bool iscounting(); // start timer number of seconds void startcounting(int value = 300); void stopcounting(); // number of seconds reach int maximum(); // current value of timer int value(); // elapsed time since timer has started int elapsedtime(); signals: // sent when timer finishes count void timeout(); // event emited @ each second when timer active void top(int remainingseconds); protected: // launch thread //virtual void run(); private slots: // decrements remaining time @ each second , emits top() void timerevent(); private: qtimer* _timer; // remaining time int _left; // number of seconds @ 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() { // test if timer still active return _timer->isactive(); } void timer::startcounting(int value) { qdebug() << qstring("start timer %1 secs").arg(qstring::number(value)); if(_left != 0 || _timer->isactive()) { _timer->stop(); } _maximum = value; _left = value; // emit first top emit top(_left); // start timer: 1000 msecs _timer->start(1000); // start thread start(); } void timer::stopcounting() { qdebug() << qstring("stopping timer @ %1 secs => %2 secs remaining.").arg(qstring::number(elapsedtime()), qstring::number(_left)); // stop timer _timer->stop(); _left = 0; _maximum = 0; // kill thread terminate(); } int timer::maximum() { return _maximum; } int timer::value() { return _left; } void timer::timerevent() { qdebug() << "timer event"; if(--_left == 0) { // stop timer _timer->stop(); // emit end of timer emit timeout(); // stop thread terminate(); } else { // emit signal @ each second emit top(_left); } } int timer::elapsedtime() { return (_maximum - _left); }
edit
i realized object tried move thread singleton. lead problem (see here).
you don't need subclass qthread in particular case. , in general, abstain subclassing qthread unless sure need.
here quick example how setup worker , timer in thread , launch it:
the worker class:
class worker : public qobject { q_object public: explicit worker(qobject *parent = 0) : qobject(parent) {} signals: void dosomething(); public slots: void trigger() { emit dosomething(); } };
main.cpp
int main(int argc, char *argv[]) { qcoreapplication a(argc, argv); mainthreadobject o; qthread *thread = new qthread; worker w; qtimer timer; timer.setinterval(1000); timer.movetothread(thread); w.movetothread(thread); qobject::connect(thread, signal(started()), &timer, slot(start())); qobject::connect(&w, signal(dosomething()), &o, slot(dosomething())); qobject::connect(&timer, signal(timeout()), &w, slot(trigger())); thread->start(); return a.exec(); }
so, have mainthreadobject
represents qobject derived living in main thread. create timer , worker
object, used wrap signal , slot avoid need of subclassing qthread. timer setup , , worker moved new thread, thread started()
signal connected timer start()
slot, worker dosomething()
signal connected main thread object dosomething()
slot, , timer timeout()
signal connected worker trigger()
slot. thread started initiates entire chain in event loop.
as result, mainthreadobject::dosomething()
called every second, signal emitted secondary thread.
Comments
Post a Comment