QObject 是所有 Qt 对象的基类,在 Qt 中提供基本计时器支持。采用 QObject::startTimer (),采用间隔 (以毫秒为单位) 作为自变量启动计时器。函数返回唯一整型计时器 ID。然后以常规间隔激发计时器,直到明确调用 QObject::killTimer () 采用该计时器 ID。
代替直接处理计时器 ID,可以使用 QBasicTimer . QBasicTimer 是值类, RAII 包裹器围绕计时器 ID。启动计时器采用 QBasicTimer::start (),和停止它采用 QBasicTimer::stop () (后者还会被调用当销毁时)。要使用 QBasicTimer ,必须重实现 timerEvent () 在类 (必须是子类化的 QObject ),并在那里处理计时器事件。
此机制要工作,应用程序必须在事件循环中运行。可以启动事件循环采用 QApplication::exec ()。当计时器激发时,应用程序发送 QTimerEvent ,并控制流离开事件循环,直到计时器事件被处理。这隐含计时器无法被激发,当应用程序忙于做某些事情时。换句话说:计时器精度从属应用程序的粒度。
在多线程应用程序中,可以在拥有事件循环的任何线程中使用计时器机制。要从非 GUI 线程启动事件循环,使用 QThread::exec ()。Qt 使用对象的 线程亲缘关系 确定哪个线程将交付 QTimerEvent 。因此,必须启动和停止对象线程中的所有计时器;为另一线程中的对象启动计时器,是不可能的。
计时器功能的主要 API 是 QTimer . QTimer 以有符号整数存储间隔,把它支持的最大间隔,以有符号整数限制到可以拟合的毫秒数 (实际上,这大约是 24 天的周期)。
Qt 6.8 引入了
QChronoTimer
类。2 个类的主要差异是
QChronoTimer
支持更大间隔范围和更高精度 (
std::chrono::nanoseconds
)。对于
QTimer
最大支持间隔为 ±24 天,而
QChronoTimer
是 ±292 年。若只需要毫秒分辨率和 ±24 天范围,可以继续使用
QTimer
。注意,
QChronoTimer
的存在主要是因为
QTimer
的精度无法被改为
std::chrono::nanoseconds
不破坏二进制兼容性。
计时器的精度从属底层 OS (操作系统)。Windows 2000 拥有 15ms 精度;我们有测试过其它系统,可以处理 1ms 间隔。
QTimer 提供发射信号的常规计时器,当计时器激发时,并继承自 QObject 因此,它能很好适应大多数 Qt 程序的所有权结构。正常使用它的方式像这样:
QTimer *timer = new QTimer(1s, this);
connect(timer, &QTimer::timeout, this, &MyWidget::processOneThing);
timer->start();
auto *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &MyWidget::processOneThing);
timer->setInterval(1s);
timer->start();
The
QTimer
对象被制作成子级对于
this
对象,因此当
this
被销毁,计时器也被销毁。接下来,
timeout
() 信号被连接到将做工作的槽,可以把计时器间隔传递给构造函数,或稍后设置采用 setInterval()。
QTimer 还为单发计时器提供静态函数。例如:
MyWidget widget;
QTimer::singleShot(200ms, &widget, &MyWidget::updateCaption);
200 毫秒后这执行代码行,
updateCaption()
槽将被调用。
For QTimer 要工作,应用程序必须拥有事件循环;也就是说,必须调用 QCoreApplication::exec () 在某些地方。才交付计时器事件,当事件循环在运行时。
在多线程应用程序中,可以使用 QTimer 在拥有事件循环的任何线程中。要从非 GUI 线程启动事件循环,使用 QThread::exec ()。Qt 使用计时器的 线程亲缘关系 确定哪个线程将发射 timeout () 信号。因此这,必须在其线程中启动和停止计时器;从另一线程启动计时器,是不可能的。
The
指针式时钟
范例展示如何使用
QTimer
以按定期间隔重新绘制 Widget。来自
AnalogClock
的实现:
AnalogClock::AnalogClock(QWidget *parent) : QWidget(parent) { QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, QOverload<>::of(&AnalogClock::update)); timer->start(1000); setWindowTitle(tr("Analog Clock")); resize(200, 200); }
每秒, QTimer 会调用 QWidget::update () 槽以刷新时钟的显示。