QThread и QTimer

Я работаю над приложением, разработанным с Qt 4.6.

Я хочу создать пользовательский таймер, который учитывается в отдельном streamе. Тем не менее, я хочу, чтобы этот таймер мог отправлять сигналы в основной stream.

Я подclassифицировал QThread, но он, похоже, не работает.

Вот Timer.h:

#ifndef TIMER_H #define TIMER_H #include  #include  #include  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:

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

РЕДАКТИРОВАТЬ

Я понял, что объект, который я пытался переместить в другой stream, был на самом деле синглом. Это может привести к проблеме ( см. Здесь ).

В этом конкретном случае вам не нужно подclassифицировать QThread. И вообще, воздерживаться от подclassа QThread, если вы не уверены, что это то, что вам нужно.

Вот краткий пример того, как настроить рабочий и таймер в streamе и запустить его:

рабочий 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(); } 

Итак, у нас есть MainThreadObject который представляет собой QObject, полученный в основном streamе. Мы создаем объект timer и Worker , который просто используется для обертывания сигнала и слота, чтобы избежать необходимости подclassификации QThread. Таймер настроен, и он и рабочий перемещаются в новый stream, сигнал start() streamа started() подключен к слоту start() таймера, рабочий doSomething() подключается к основному doSomething() и, наконец, сигнал timeout() таймера timeout() подключается к слоту рабочего trigger() . Затем запускается stream, который инициирует всю цепочку в цикле событий.

В результате, MainThreadObject::doSomething() вызывается каждую секунду с сигналом, испускаемым из вторичного streamа.

Пытаться

 QMetaObject::invokeMethod(&timer, "start", Qt::QueuedConnection); //timer->start() 

если вы хотите немедленно запустить таймер

Или же

 QMetaObject::invokeMethod(&timer, "start", Qt::QueuedConnection , Q_ARG(int, 1000 )); //timer->start(200) 

если вы хотите запустить таймер после 1000 секунд

В streamе без GUI (обратный вызов QThread или Pthread)

Во-первых, если вы подclassом из QThread, вам нужно реализовать метод run (), если нет, то нет смысла это делать, вы можете наследовать от QObject.

Во-вторых, ваш QTimer должен находиться в streamе, который запускает цикл событий. Без контура событий никакие Qt-сигналы в очереди не могут быть переданы. Вы можете запустить цикл событий, вызвав exec () в методе запуска streamа:

 void Timer::run() { exec(); } 

Вероятная причина может быть, ваш объект-таймер не находится в streamе с циклом события. Для запуска сигналов требуется цикл событий.

Тем не менее, я бы сказал, что вы не должны идти с таким подходом. Таймеры используют разные механизмы на разных платформах, и ваш код может не соответствовать ожиданиям на разных платформах.