我正在尝试在特定线程中启动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";
}
答案 0 :(得分:24)
正如我评论的那样(链接中的更多信息),你做错了:
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版本&gt; = 4.7)默认情况下QThread
在他的run()
方法中启动一个事件循环。要在线程内运行,只需移动对象即可。 Read the doc...
答案 1 :(得分:12)
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();
答案 2 :(得分:9)
QTimer
仅适用于具有事件循环的线程。
http://qt-project.org/doc/qt-4.8/QTimer.html
在多线程应用程序中,您可以在任何具有事件循环的线程中使用QTimer。要从非GUI线程启动事件循环,请使用QThread :: exec()。 Qt使用计时器的线程亲和性来确定哪个线程将发出timeout()信号。因此,您必须在其线程中启动和停止计时器;无法从另一个线程启动计时器。
答案 3 :(得分:1)
您可以使用发射信号并在发射的插槽功能中启动计时器
的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);
}
答案 4 :(得分:0)
您需要一个事件循环才能拥有计时器。以下是我用代码解决同样问题的方法:
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()
进入主事件循环并等待直到调用exit()。返回 设置为exit()的值(如果通过调用exit(),则为0) 放弃())。有必要调用此函数来启动事件 处理。主事件循环从窗口系统接收事件 并将这些发送到应用程序小部件。让你的 应用程序执行空闲处理(即执行特殊功能) 每当没有待处理的事件时),使用QTimer为0超时。 使用可以实现更高级的空闲处理方案 processEvents()。
答案 5 :(得分:0)
我创建了一个在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();
}