QT笔记 ---定时器

来源:互联网 发布:知乎 yuhang liu 编辑:程序博客网 时间:2024/06/03 06:43
参考: http://qt-project.org/wiki/QtTimers_SimplifiedChinese 

定时器的 API

Qt 提供了两套 计时器的 API

  • QObject::startTimer [doc.qt.nokia.com] – 创建一个由QObject的任意子类使用的循环定时器,并返回定时器的ID。当定时时间到时它会收到一个 QEvent::Timer,可以通过覆盖QObject::timerEvent(QTimerEvent*)进行处理。该QTimerEvent参数包含定时器ID,当QObject使用多个定时器时可以进行匹配选择。 QObject::killTimer(id) 可用于停止和解除计时器。

  • QTimer [doc.qt.nokia.com] – QTimer 是一个当定时时间到时发射 timeout() 信号的 QObject。它简单地使用 QObject::startTimer() 并在事件处理器 QObject::timerEvent() 中发射 timeout() 信号。
  • 定时器 id 分配算法
  • 定时器ID的分配算法是无锁的。

    一个重要的事实是,定时器ID必须是唯一的(甚至在跨线程的情况下)。这是因为当一个QObject从一个线程移动到另一个时,它的定时器也会随它一起移动(即信号和事件现在要通过新线程的事件循环进行传递)。移动定时器是一个简单从旧线程的派发器注销计时器并在在新线程的派发器中注册的问题。如果定时器的ID是不是唯一的,定时器ID可能会与新线程中现有的定时器发生冲突。如果新的定时器ID在QObject::moveToThread时被重新生成,那么应用程序需要被通知id信息发生更改,而且这对程序员来说是一个麻烦。

    API 实现

    QObject::startTimer 使用事件派发器注册一个新的定时器。这大约等价于,QAbstractEventDispatcher::instance(object->thread())->registerTimer(interval, object).

    QTimer 是一个 QObject。他所做的就是 QObject::startTimer()。它在自己的timerEvent()中发射 activated() 信号。

    QBasicTimer

    QTimer由于本身是一个QObject所以显得比较笨拙,而且Qt代码一般都尽量避免使用它。与此同时,使用 QObject::startTimer()API 又比较容易出错。

    1. 当停止定时器时,在QObject::killTimer(m_timerId)后你必须使定时器id变无效(比如说-1)。这是需要的,因为m_timerId的正值在你的代码中指示该定时器处于激活状态。

    1. 要重启一个定时器,你需要牢记如果m_timerId不为-1的话要杀死(kill)掉老的定时器。

    QBasicTimer 解决了上面这个问题,它只是整数 “timer id” 的一个华而不实的接口。QBasicTimer::start(int msec, QObject *) 将杀死任何可能存在的定时器并使用 object->startTimer(msec) 创建一个新的。QBasicTimer::stop() 将杀死该定时器并使得id无效。QBasicTimer::timerId() 提供定时器 id。