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 expired
        removeFirst();
        //从这里可以看出,下次触发时间是在调用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 inactive
    for (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 found
    return false;
}

void QObject::timerEvent(QTimerEvent *)

QObject默认空实现


void QObject::timerEvent(QTimerEvent *)
{
}

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

myobject.h

#include
class myobject : public QObject
{
    Q_OBJECT
public:
    myobject(QObject *parent = nullptr):QObject(parent){
    }
protected:
virtual void timerEvent(QTimerEvent *event);
};

myobject.cpp

#include
virtual void timerEvent(QTimerEvent *event)
{
     qDebug()<<"timerId="<timerId();
}

main.cpp

int 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();
}

你可能感兴趣的:(qt,qt)