QObject_timer

2024-01-10 22:20
文章标签 timer qobject

本文主要是介绍QObject_timer,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

QObject

int QObject::startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer)

QObject本身自带的定时器函数,简单的定时任务不需要再使用QTimer,只需要重写timerEvent即可。
interval单位是毫秒,且必须大于等于0
如果interval为0,则每当没有更多的窗口系统事件需要处理时,计时器事件发生一次。

Qt::TimerType:枚举类型有3个值
Qt::PreciseTimer :精确计时器试图保持毫秒级的精度
Qt::CoarseTimer :粗定时器试图将准确度保持在所需间隔的5%以内(默认值)
Qt::VeryCoarseTimer :非常粗糙的计时器只保持完整的秒精度

返回定时器标识符,如果无法启动定时器则返回零。

  1. 调用startTimer后每间隔interval毫秒,触发一次timerEvent事件,直到killTimer()被调用或者对象析构。
  2. 多次调用startTimer,会添加多个定时器,根据返回的id判断是触发的那个定时器超时事件
  3. 间隔的计算:在触发timerEvent前已经设置好了下次触发的超时时间
  4. 每次事件循环都会检查所有的定时器,循环触发所有已经超时的定时器事件(触发前已经设置好下次的超时时间)
  5. movethread会导致定时器重新开始计时,频繁的movethread可能会导致无法触发timerEvent
int QObject::startTimer(int interval, Qt::TimerType timerType)
{Q_D(QObject);if (Q_UNLIKELY(interval < 0)) {qWarning("QObject::startTimer: Timers cannot have negative intervals");return 0;}auto thisThreadData = d->threadData.loadRelaxed();if (Q_UNLIKELY(!thisThreadData->hasEventDispatcher())) {qWarning("QObject::startTimer: Timers can only be used with threads started with QThread");return 0;}//必须在同一线程调用才有效if (Q_UNLIKELY(thread() != QThread::currentThread())) {qWarning("QObject::startTimer: Timers cannot be started from another thread");return 0;}//向事件分发器注册定时器int timerId = thisThreadData->eventDispatcher.loadRelaxed()->registerTimer(interval, timerType, this);if (!d->extraData)d->extraData = new QObjectPrivate::ExtraData;d->extraData->runningTimers.append(timerId);//append意味着可以添加多个定时器return timerId;
}registerTimer-》timerInsert(将timer加入列表当中,并按照触发先后顺序排列)void QTimerInfoList::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
{QTimerInfo *t = new QTimerInfo;t->id = timerId;t->interval = interval;t->timerType = timerType;t->obj = object;t->activateRef = nullptr;timespec expected = updateCurrentTime() + interval;t->timeout = expected;//超时时间timerInsert(t);
}
每次事件循环processEvents时,调用activateTimers处理
int QTimerInfoList::activateTimers()
{int n_act = 0, maxCount = 0;firstTimerInfo = nullptr;timespec currentTime = updateCurrentTime();//先找到所有到期的定时器,后面依次调用sendEvent触发timerEvent处理事件for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) {if (currentTime < (*it)->timeout)break;maxCount++;}while (maxCount--) {if (isEmpty())break;QTimerInfo *currentTimerInfo = constFirst();if (currentTime < currentTimerInfo->timeout)break; // no timer has expiredremoveFirst();//从这里可以看出,下次触发时间是在调用timerevent前就已经计算好了的,//如果timerevent执行时间较长大于时间间隔interval,下次事件循环判断其超时会直接触发calculateNextTimeout(currentTimerInfo, currentTime);//计算下次触发时间timerInsert(currentTimerInfo);//下次的超时信息并加入到超时列表里面,按照超时先后顺序排列的if (!currentTimerInfo->activateRef) {QTimerEvent e(currentTimerInfo->id);QCoreApplication::sendEvent(currentTimerInfo->obj, &e);//最终调用到timerevent,同步触发}}return n_act;
}void QTimerInfoList::timerInsert(QTimerInfo *ti)
{int index = size();while (index--) {const QTimerInfo * const t = at(index);if (!(ti->timeout < t->timeout))//按触发先后顺序排列,timeout小的排在前面break;}insert(index+1, ti);
}

void QObject::killTimer(int id)

id为startTimer的返回值
killTimer被调用时将结束对应的定时器,其不再触发timerEvent事件。
注意:不能在另一个线程里面结束它,即在另一个线程调用此函数无效,定时器不会被结束

void QObject::killTimer(int id)
{Q_D(QObject);//不能在另一个线程里面结束它if (Q_UNLIKELY(thread() != QThread::currentThread())) {qWarning("QObject::killTimer: Timers cannot be stopped from another thread");return;}if (id) {auto thisThreadData = d->threadData.loadRelaxed();if (thisThreadData->hasEventDispatcher())thisThreadData->eventDispatcher.loadRelaxed()->unregisterTimer(id);d->extraData->runningTimers.remove(at);QAbstractEventDispatcherPrivate::releaseTimerId(id);}
}bool QTimerInfoList::unregisterTimer(int timerId)
{// set timer inactivefor (int i = 0; i < count(); ++i) {QTimerInfo *t = at(i);if (t->id == timerId) {//移除removeAt(i);if (t == firstTimerInfo)firstTimerInfo = nullptr;if (t->activateRef)*(t->activateRef) = nullptr;delete t;return true;}}// id not foundreturn false;
}

void QObject::timerEvent(QTimerEvent *)

QObject默认空实现


void QObject::timerEvent(QTimerEvent *)
{
}

一般都是继承后重写实现自己的功能

myobject.h#include<QObject>
class myobject : public QObject
{Q_OBJECT
public:myobject(QObject *parent = nullptr):QObject(parent){}
protected:
virtual void timerEvent(QTimerEvent *event);
};myobject.cpp#include<QTimerEvent>
virtual void timerEvent(QTimerEvent *event)
{qDebug()<<"timerId="<<event->timerId();
}main.cppint main(int argc, char *argv[])
{QApplication a(argc, argv);myobject *obj1= new  myobject(nullptr);obj1->startTimer(1000);obj1->startTimer(5000);obj1->startTimer(10000);return a.exec();
}

这篇关于QObject_timer的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/592257

相关文章

4.15 版本内核调用 init_timer()函数出错

linux/include/linux/timer.h4.15 之前版本struct timer_list {14 /*15 * All fields that change during normal runtime grouped to the16 * same cacheline17 */18 struct hl

java AWT 绘图,实现弹球游戏,有实现keylistener,timer功能

Timer(int delay, ActionListener listener):每间隔delay毫秒,系统自动触发ActionListener监听器里的事件处理器(actionPerformed()方法)。 package javaAWT;import java.awt.Canvas;import java.awt.Color;import java.awt.Dimension;imp

Timer和ScheduledThreadPoolExecutor

文章来源: https://blog.csdn.net/u013332124/article/details/79603943 在jdk自带的库中,有两种技术可以实现定时任务。一种是使用Timer,另外一个则是ScheduledThreadPoolExecutor。下面为大家分析一下这两个技术的底层实现原理以及各自的优缺点。 一、Timer 1. Timer的使用

Android -- 视频音频多媒体播放,在线播放, MediaPlayer, SurfaceView, SoundPool, Timer定时器使用

1. SoundPool 用于快速重复的播放短音频 [java]  view plain copy public class MainActivity extends Activity {       private SoundPool soundPool;       private int soundId;          @Override       protec

Android开发Timer计时器的操作实例

本文内容讲的是Android开发中Timer计时器如何实现。实际上Timer和TimerTask都是JDK自带的功能,两个类结合可以实现定时任务执行一次,或者定期重复执行任务。 下面模拟一个Android开发Timer计时器实例:   1、新建一个项目:Lesson34_Timer2、MainActivity.java代码如下:   package basic.android.timer

STM32CUBEIDE FreeRTOS操作教程(四):timer软件定时器

STM32CUBEIDE FreeRTOS操作教程(四):timer软件定时器 STM32CUBE开发环境集成了STM32 HAL库进行FreeRTOS配置和开发的组件,不需要用户自己进行FreeRTOS的移植。这里介绍最简化的用户操作类应用教程。以STM32F401RCT6开发板为例,只用到USB,USART1极少的接口,体现FreeRTOS的各种操作过程。 操作教程(四)配置FreeRTO

QObject 信号与槽原理

只有继承了QObject类的类,才具有信号槽的能力。所以,为了使用信号槽,必须继承QObject。凡是QObject类(不管是直接子类还是间接子类),都应该在第一行代码写上Q_OBJECT。不管是不是使用信号槽,都应该添加这个宏。这个宏的展开将为我们的类提供信号槽机制、国际化机制以及 Qt 提供的不基于 C++ RTTI 的反射能力。因此,如果你觉得你的类不需要使用信号槽,就不添加这个宏,就是错误

QObject::moveToThread(QThread * targetThread)

改变该对象及其孩子的所在的线程。如果该对象有父亲,则它不能被移动。 事件处理将在targetThread中继续。 移动一个对象到主线程,使用QApplication::instance()来得到当前application的指针,使用QApplication()::thread()来得到应用程序所在的线程。例如: myObject->moveToThread(QApplication:

江山易改本性难移之ZYNQ SDK API函数笔记(Timer)

初学Xilinx ZYNQ SDK的开发,下面记录使用到的API函数及自己的理解。若有误,还请指教。 Timer函数 常用编程步骤: 1.查找输入设备的ID查找设备; 2.输入的配置信息初始化; 3.加载计数周期; 4.设置自动装载模式; 5.启动定时器; 配置GPIO只需要以上5个步骤。 1、XGpioPs_Config *XGpioPs_LookupConfig(u16 Devi

最近用Timer踩了一个坑,分享一下避免别人继续踩

最近做一个小项目,项目中有一个定时服务,需要向对方定时发送数据,时间间隔是1.5s,然后就想到了用C#的Timer类,我们知道Timer 确实非常好用,因为里面有非常人性化的start和stop功能,在Timer里面还有一个Interval,就是用来设置时间间隔,然后时间间隔到了就会触 发Elapsed事件,我们只需要把callback函数注册到这个事件就可以了,如果Interval到了