[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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.