赞
踩
在 Qt 中,如果想要定时执行某些事件或函数,通常会使用 QTimer 类。QTimer 允许设置一个时间间隔,当这个时间间隔过去后,它会发出一个信号。可以将这个信号连接到一个槽函数,从而在该时间间隔到达时执行特定的操作。如果想要实现定时的操作是异步执行 (不阻塞主线程),可通过
moveToThread
将定时器移动到一个线程中,信号和槽的连接类型使用Qt::DirectConnection
,保证槽函数执行是在定时器的线程中。效果如下图所示 (一秒执行一次):
this->m_timer = new QTimer(nullptr);
this->m_thread = new QThread(this);
m_timer->setInterval(1000);
m_timer->moveToThread(m_thread);
connect(m_timer, &QTimer::timeout, this, [&](){
QString time = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
qDebug()<< time << " timer Thread ID:" << QThread::currentThreadId();
}, Qt::DirectConnection);
connect(m_thread, &QThread::started, m_timer, QOverload<>::of(&QTimer::start));
connect(m_thread, &QThread::finished, m_timer, &QTimer::stop);
m_thread->start();
qDebug() << "Main Thread ID:" << QThread::currentThreadId();
首先创建定时器和线程,设定定时器间隔时间为1秒,并将定时器移动到线程中。方便起见直接使用兰姆达表达式设定定时器的定时槽函数. 使用信号和槽的形式调用定时器相关函数 (开始和停止
)。最后启动线程即可.
m_thread->quit();
m_thread->wait();
m_thread->deleteLater();
m_timer->deleteLater();
一般在父类或者父窗体的析构函数中执行,停止执行,释放内存。
信号与槽相关知识可参考:
Qt 信号与槽的使用详解 - 多种绑定形式、同步异步、Lambda表达式等:https://blog.csdn.net/qq_38204686/article/details/139702275
m_timer->stop();
会显示QObject::killTimer: Timers cannot be stopped from another thread
。可参考
Qt: QTimer和QThread:https://www.cnblogs.com/lingdhox/p/4218051.html
https://stackoverflow.com/questions/53200294/qthread-with-qtimer-connection-issues
QOverload<>::of
重载&QTimer::start
有多个重载
函数,比如void QTimer::start(int msec)
和void QTimer::start()
,需使用QOverload<>::of
指定调用哪一个重载函数 - (在<>中指明参数,比如<int>
)。connect(m_thread, &QThread::started, m_timer, &QTimer::start);
会报错,connect(m_thread, SIGNAL(started()), m_timer, SLOT(start()));
是可行的,但不建议。可参考
QThread with QTimer connection issues:https://stackoverflow.com/questions/53200294/qthread-with-qtimer-connection-issues
QT-信号槽有多个重载版本{ QOverload<_>::of(&::) }:https://blog.csdn.net/ugetoneshot/article/details/139169027
new QTimer(nullptr)
参数parent
为空而不是this
void QObject::moveToThread(QThread *targetThread)
的官方解释:
更改此对象及其子对象的线程相关性。如果对象有父对象,则无法移动该对象,事件处理将在targetThread中继续。使用时需注意:此函数只能将对象从当前线程“推”到另一个线程,而不能将对象从任意线程“拉”到当前线程。
setTimerType(Qt::PreciseTimer);
之后误差只有1毫秒。
可参考
QT使用高精度定时器:https://blog.csdn.net/ljjjjjjjjjjj/article/details/130189550
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。