QThread和QTimer [英] QThread and QTimer

查看:988
本文介绍了QThread和QTimer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Qt 4.6开发的应用程序。

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.

我是QThread的子类,但它似乎不工作。

I subclassed QThread but it doesn't seem to work.

这里是Timer.h:

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

并且Timer.cpp:

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 for %1 secs").arg(QString::number(value));
    if(_left != 0 || _timer->isActive())
    {
         _timer->stop();
    }

    _maximum = value;
    _left = value;

    // emit the first top
    emit top(_left);

    // start the timer: 1000 msecs
    _timer->start(1000);

    // start the thread
    start();
}

void Timer::stopCounting()
{
    qDebug() << QString("Stopping timer at %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 a signal at each second
        emit top(_left);
    }
}

int Timer::elapsedTime()
{
    return (_maximum - _left);
}

EDIT

我意识到我试图移动到另一个线程的对象实际上是一个单例。这可能会导致问题(请参阅此处)。

I realized the object I tried to move to another thread was actually a singleton. It could lead to a problem (see here).

推荐答案

在这种特殊情况下,你不需要继承QThread。一般来说,除非你确定它是你需要的,否则不要对QThread进行子类化。

You don't need to subclass QThread in this particular case. And in general, abstain from subclassing QThread unless you are sure it is what you need.

这是一个快速示例,说明如何在线程中设置工作程序和计时器并启动它:

Here is a quick example how to setup a worker and timer in a thread and launch it:

工人类:

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();
}

因此,我们有 MainThreadObject 它代表一个QObject派生于主线程中。我们创建了定时器和 Worker 对象,它只是用来包装一个信号和槽,以避免需要子类化QThread。定时器被设置,并且它和worker被移动到新线程,线程 started()信号被连接到定时器 start() doSomething()信号连接到主线程对象 doSomething()槽,并且最后定时器 timeout()信号连接到工人 trigger()插槽。

So, we have the MainThreadObject which represents a QObject derived living in the main thread. We create the timer and Worker object, which is just used to wrap a signal and slot to avoid the need of subclassing QThread. The timer is setup and it and the worker are moved to the new thread, the thread started() signal is connected to the timer start() slot, the worker doSomething() signal is connected to the main thread object doSomething() slot, and finally the timer timeout() signal is connected to the worker trigger() slot. Then the thread is started which initiates the entire chain in the event loop.

结果, MainThreadObject :: doSomething()每秒调用一次,从辅助线程发出信号。

As a result, the MainThreadObject::doSomething() is called every second, with the signal emitted from the secondary thread.

这篇关于QThread和QTimer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆