我想在一个特定的线程启动QTimer。 但是,计时器似乎并没有执行,没有什么是打印出来。 它是什么做的计时器,该槽或线程?
main.cpp中
#include "MyThread.h"
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
MyThread t;
t.start();
while(1);
}
MyThread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QTimer>
#include <QThread>
#include <iostream>
class MyThread : public QThread {
Q_OBJECT
public:
MyThread();
public slots:
void doIt();
protected:
void run();
};
#endif /* MYTHREAD_H */
MyThread.cpp
#include "MyThread.h"
using namespace std;
MyThread::MyThread() {
moveToThread(this);
}
void MyThread::run() {
QTimer* timer = new QTimer(this);
timer->setInterval(1);
timer->connect(timer, SIGNAL(timeout()), this, SLOT(doIt()));
timer->start();
}
void MyThread::doIt(){
cout << "it works";
}
正如我评论(在链接的详细信息),你错了这样做:
- 你与另一个对象混合对象容纳线程数据(负责的
doIt()
他们要分开。 - 有没有需要继承
QThread
你的情况。 更糟的是,你要重写的run
,而不考虑它在做什么方法。
的这部分程序应该是足够
QThread* somethread = new QThread(this);
QTimer* timer = new QTimer(0); //parent must be null
timer->setInterval(1);
timer->moveToThread(somethread);
//connect what you want
somethread->start();
现在(的Qt版本> = 4.7),默认QThread
在他开始一个事件循环run()
方法。 为了一个线程中运行,你只需要移动的对象。 阅读文档...
m_thread = new QThread(this);
QTimer* timer = new QTimer(0); // _not_ this!
timer->setInterval(1);
timer->moveToThread(m_thread);
// Use a direct connection to whoever does the work in order
// to make sure that doIt() is called from m_thread.
worker->connect(timer, SIGNAL(timeout()), SLOT(doIt()), Qt::DirectConnection);
// Make sure the timer gets started from m_thread.
timer->connect(m_thread, SIGNAL(started()), SLOT(start()));
m_thread->start();
一个QTimer
只适用于具有事件循环的线程。
http://qt-project.org/doc/qt-4.8/QTimer.html
在多线程应用程序,你可以在有事件循环任何线程使用QTimer。 要开始从非GUI线程的事件循环,使用的QThread :: EXEC()。 Qt使用计时器的线程关联性,以确定哪些线程将发射超时()信号。 正因为如此,你必须启动和停止在其线程定时器; 这是不可能开始从另一个线程的计时器。
You can use the emit signal and start the timer inside the emitted slot function
main.cpp
#include "MyThread.h"
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
MyThread t;
t.start();
while(1);
}
MyThread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QTimer>
#include <QThread>
#include <iostream>
class MyThread : public QThread {
Q_OBJECT
public:
MyThread();
QTimer *mTimer;
signals:
start_timer();
public slots:
void doIt();
void slot_timer_start();
protected:
void run();
};
#endif /* MYTHREAD_H */
MyThread.cpp
#include "MyThread.h"
using namespace std;
MyThread::MyThread() {
mTimer = new QTimer(this);
connect(this,SIGNAL(start_timer()),this, SLOT(slot_timer_start()));
connect(mTimer,SIGNAL(timeout()),this,SLOT(doIt()));
}
void MyThread::run() {
emit(start_timer());
exec();
}
void MyThread::doIt(){
cout << "it works";
}
void MyThread::slot_timer_start(){
mTimer->start(1000);
}
你需要一个事件循环有定时器。 以下是我解决我的代码相同的问题:
MyThread::MyThread() {
}
void MyThread::run() {
QTimer* timer = new QTimer(this);
timer->setInterval(1);
timer->connect(timer, SIGNAL(timeout()), this, SLOT(doIt()));
timer->start();
/* Here: */
exec(); // Starts Qt event loop and stays there
// Which means you can't have a while(true) loop inside doIt()
// which instead will get called every 1 ms by your init code above.
}
void MyThread::doIt(){
cout << "it works";
}
下面是相关的部分,没有任何其他的海报中提到的文件:
INT QCoreApplication :: EXEC()
进入主事件循环并等待退出()被调用。 返回设定为退出()中的值(其为0,如果出口()通过调用退出())。 有必要调用这个函数来启动事件处理。 主事件循环从窗口系统接收事件,并分派到这些应用程序部件。 为了使您的应用程序执行的空闲处理(即执行一个特殊的函数,只要没有未决事件),使用QTimer 0超时。 可使用processEvents来实现更高级的空闲处理方案()。
我创建了一个调用lambda函数中的计时器的例子:
#include <QCoreApplication>
#include <QObject>
#include <QTimer>
#include <QThread>
#include <QDebug>
#include <memory>
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
QThread* thread = new QThread(&app);
QObject::connect(thread, &QThread::started, [=]()
{
qInfo() << "Thread started";
QTimer* timer1 = new QTimer(thread);
timer1->setInterval(100);
QObject::connect(timer1, &QTimer::timeout, [=]()
{
qInfo() << "Timer1 " << QThread::currentThreadId();
});
timer1->start();
});
thread->start();
QTimer timer2(&app);
QObject::connect(&timer2, &QTimer::timeout, [=]()
{
qInfo() << "Timer2 " << QThread::currentThreadId();
});
timer2.setInterval(100);
timer2.start();
return app.exec();
}