本文主要是介绍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 :非常粗糙的计时器只保持完整的秒精度
返回定时器标识符,如果无法启动定时器则返回零。
- 调用startTimer后每间隔interval毫秒,触发一次timerEvent事件,直到killTimer()被调用或者对象析构。
- 多次调用startTimer,会添加多个定时器,根据返回的id判断是触发的那个定时器超时事件
- 间隔的计算:在触发timerEvent前已经设置好了下次触发的超时时间
- 每次事件循环都会检查所有的定时器,循环触发所有已经超时的定时器事件(触发前已经设置好下次的超时时间)
- 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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!