定时器QTimer和timerEvent事件重载的使用区别记录
QTimer定时器
一般情况下我们使用定时器开启定时任务都是这样操作:
//.h文件--声明QTimer对象和槽函数
public slots:
void Timer_func();
public:
QTimer* Timer_;
//.cpp文件--实例化和连接信号槽
Timer_= new QTimer();
Timer_->setInterval(6000); //6s
connect(Timer_, SIGNAL(timeout()), this, SLOT(Timer_func()));
Timer_->start();
这样做很明确,且是专门一个信号来触发定时任务,不会导致冲突。但是这需要每一个不同的定时任务对应开一个QTimer。有些对象内部轮询的任务,用QTimer定时就有点麻烦(懒),所以找到了另外一种方法,它就是QObject提供的定时器方法。
QObject中的timerEvent事件重载-QObject定时器
通常使用startTimer()要比QTimer有更好的使用效率,下面是官方文档原话翻译,节选自QObject class里的startTimer()
函数下方注解。
启动计时器并返回一个计时器标识符,如果启动失败则返回零。
计时器事件将每毫秒发生一次,直到调用killTimer()。
如果标识符返回interval为0,则计时器事件在每次没有更多窗口系统事件需要处理时发生一次。
当计时器事件发生时,使用QTimerEvent事件参数类调用虚拟timerEvent()函数。
重载此函数以获取计时器事件。
如果有多个计时器在运行,QTimerEvent::timerId()可以用来找出哪个计时器被激活了。
(说人话)所有继承自QObject的类,都会有一个timerEvent(QTimerEvent *event)
的纯虚函数,我们只需要继承QObject,startTimer()
设定定时间隔,再重载这个函数以处理自己的定时任务。多个定时任务用timeId区分,结束后使用killTimer(timerid)
关闭定时任务。
void timerEvent(QTimerEvent *event) override; 可以加override ,表示覆盖
.h文件内定义定时器ID:
.cpp 文件中重载timerEvent,使用startTimer(timerId)
开启定时器,使用killTimer(timerId)
关闭定时器。逻辑里通过验证timeID
实现不同功能:
Delay_MSec(INT msec)实现了QT中的非阻塞延时,适合在对象内部自延时而不卡住其他事件(如界面事件)。
void MainWindow::Delay_MSec(unsigned int msec)
{
QTime _Timer = QTime::currentTime().addMSecs(msec); // 在当前的时间上增加多少秒
while( QTime::currentTime() < _Timer ) // while循环
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);// 期间在做主事件循环,就避免了阻塞
// 去掉这句就是阻塞延时了
}
另外,timerEvent事件最好不要处理过久,因为如果这个事件函数被占用了,下一次的startTimer
定时器事件也会无法响应。(如有补充欢迎指正!)
示例,大家也可以自己做测试:
图片文字里的32秒是错的 ,应该是33秒,小错误忽略掉就好~
总结
QTimer适用性相对较广,因为它的使用一般是基于信号与槽,所以可通过信号或槽的多级绑定以实现更为复杂的定时任务。且可以同一时间被触发多次,还可以跨线程。
timerEvent
事件则适用面则相对较窄,它的实现是基于继承和重载,意味着只有该类和该类的子类生成的实例能看到这个定时事件。这适合在较少工作量的定时轮询场景中使用。但是timerEvent
不允许占用时间过长,因为它们本质上还是同一条线程。
提一嘴,QT 中,信号与槽是否是同一条线程要看connect函数的第五个参数。
直接连接是信号发出同时 立刻执行 槽函数,跟回调类似,是在同一条线程。执行完槽函数才会继续往下执行。
队列连接发出信号后,信号会放到接收方的事件队列 等待执行 ,并不是同一条线程,等接收方空闲事件循环才会调用槽函数。
自动连接 这是默认参数,让Qt自行选择。如果信号发送方和接收方在同一线程中,就使用直接连接;否则使用队列连接。
简单理解:把直连当成同步,信号发出立刻调用槽;队列当成异步,等接收方空闲下来才会处理。(如果实在需要立刻响应,就调用QCoreApplication::processEvents())
参考文章
参考文章- Qt中QTimer和timerevent的区别与用法
参考文章- QObject的timerEvent使用
参考文章- 关于Qt中常用的延时方法–自我总结