定时器

QObject作为所有 Qt 对象的基类,为 Qt 提供了基本的定时器支持。通过调用 `QObject::startTimer()`,您可以以毫秒为单位的间隔作为参数启动一个定时器。该函数返回一个唯一的整数定时器 ID。随后,该定时器将以固定间隔触发,直到您显式地使用该定时器 ID 调用 `QObject::killTimer()` 为止。

与其直接处理定时器 ID,您不妨使用 `QBasicTimer`。`QBasicTimer ` 是一个围绕定时器 ID 构建的值类RAII包装器。 您可通过QBasicTimer::start()启动定时器,并通过QBasicTimer::stop()停止定时器(后者在对象销毁时也会被调用)。要使用QBasicTimer ,您必须在类中重写timerEvent()(该类必须是QObject 的子类),并在其中处理定时器事件。

要使此机制生效,应用程序必须在事件循环中运行。您可以使用QCoreApplication::exec() 启动事件循环。有关 Qt Widgets 有关应用程序的详细信息,请参阅QApplication::exec()。当定时器触发时,应用程序会发送一个QTimerEvent ,控制流将离开事件循环,直到定时器事件被处理完毕。这意味着当您的应用程序正忙于执行其他任务时,定时器无法触发。 换言之:定时器的精度取决于应用程序的粒度。定时器的精度还取决于底层操作系统和硬件。较短的时间间隔可能会被系统调度程序四舍五入或延迟,如果系统繁忙,所有定时器类型都可能比请求的时间更晚超时。有关定时器分辨率和Qt::TimerType 的更多信息,请参阅QTimer 文档。

在多线程应用程序中,您可以在任何具有事件循环的线程中使用定时器机制。若要从非 GUI 线程启动事件循环,请使用 `QThread::exec()`。 Qt 会根据对象的 `thread affinity ` 来确定由哪个线程分发 `QTimerEvent`。因此,您必须在对象所属的线程中启动和停止所有定时器;无法在其他线程中为该对象启动定时器。

定时器功能的主要 API 是 `QTimer`。`QTimer ` 将间隔存储为有符号整数,这限制了其支持的最大间隔为有符号整数所能容纳的毫秒数(实际上,这大约相当于 24 天的周期)。

Qt 6.8 引入了QChronoTimer 类。这两个类的主要区别在于,QChronoTimer 支持更大的时间间隔范围和更高的精度(std::chrono::nanoseconds )。对于QTimer ,支持的最大时间间隔为 ±24 天,而对于QChronoTimer ,则为 ±292 年。 如果您仅需毫秒级分辨率和 ±24 天的范围,可以继续使用QTimer 。请注意,QChronoTimer 的存在主要是因为无法在不破坏二进制兼容性的情况下,将QTimer 的精度更改为std::chrono::nanoseconds 。

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

将QTimer 对象设为this 对象的子对象,这样当this 被销毁时,定时器也会随之销毁。接下来,将timeout() 信号连接到负责执行工作的槽函数,定时间隔既可以传递给构造函数,也可以稍后通过 setInterval() 进行设置。

QTimer 还为单次定时器提供了静态函数。例如:

        MyWidget widget;
        QTimer::singleShot(200ms, &widget, &MyWidget::updateCaption);

在执行这行代码 200 毫秒后,updateCaption() 插槽将被调用。

要使 `QTimer ` 正常工作,您的应用程序中必须存在事件循环;也就是说,您必须在某个地方调用 `QCoreApplication::exec()`。定时器事件仅在事件循环运行时才会被分发。

在多线程应用程序中,您可以在任何具有事件循环的线程中使用QTimer 。若要从非 GUI 线程启动事件循环,请使用QThread::exec()。 Qt 会根据定时器的 `thread affinity ` 属性来确定哪个线程将发出 `timeout()` 信号。因此,您必须在该定时器所属的线程中启动和停止定时器;无法从其他线程启动定时器。

“模拟时钟”示例演示了如何使用QTimer 以固定间隔重绘小部件。以下是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()槽函数来刷新时钟的显示。

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.