Qt入门05 定时器QTimer——大丙+Gemini

Qt入门05 定时器QTimer——大丙+Gemini

https://www.bilibili.com/video/BV1Jp4y167R9

在进行窗口程序的处理过程中,经常要周期性地执行某些操作,或者制作动画效果。在 Qt 中,使用定时器可以完美解决此类周期性任务的需求。Qt 提供了两种定时器实现方式:一种是重写事件处理函数(后续章节详细讲解),本节主要介绍基于对象模型的定时器类 QTimer 的使用方法。

要使用 QTimer,只需创建一个 QTimer 类对象,调用其 start() 函数开启定时器,此后该对象就会周期性地发出 timeout() 信号。

1. 核心 API 与槽函数 (Public / Slot Functions)

1.1 QTimer 基础操作:构造、设置间隔、启停、状态判断、发送信号函数

QTimer 的生命周期和状态流转分为三个关键节点:

  1. 实例化 (new QTimer):定时器被创建,但处于停止状态。通过传入父对象指针,可以利用 Qt 的对象树机制实现内存自动回收。

  2. 设置间隔 (setInterval):仅仅是配置了定时器的属性(每次触发的时间间隔),并不会触发计时。

    • 特殊机制:如果将间隔设为 0,在调用.start()后定时器不会立刻疯狂触发,而是在窗口系统的事件队列处理完毕、处于空闲状态时才会触发。
  3. 调用启动方法 (start()):开始计时。只有在执行了 start() 之后,定时器才真正开始在后台走秒。

基础操作 API 原型

// 1. 构造函数
// 如果指定了父对象, 创建的堆内存可以自动析构
QTimer::QTimer(QObject *parent = nullptr);

// 2. 设置时间间隔
// 设置/获取定时器的时间间隔 (单位: 毫秒)
// 默认值为0,代表在系统事件队列空闲时触发
void QTimer::setInterval(int msec);
int QTimer::interval() const;

// 3. 启动/重启/停止计时器
// 启动或重启定时器 (按照已设置的 interval)
[slot] void QTimer::start();
// 以全新的 msec 间隔启动或重启定时器
[slot] void QTimer::start(int msec);
// 停止定时器
[slot] void QTimer::stop();

// 4. 判断当前定时器是否正在后台运行
// 如果定时器正在运行,返回true; 否则返回false。
bool QTimer::isActive() const;

// 5. 发射信号,当时间间隔到了之后会被自动调用,一般在connect()中作为信号函数
[signal] void QTimer::timeout();

示例代码:

场景:在 UI 中通过 startButtonstopButton 控制定时器,并在 timeLabel 上实时显示当前时间。在 mainwindow.h 中已声明成员变量 QTimer* _timer

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTimer>
#include <QDebug>
#include <QTime>
#include <QVariant>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 1. 实例化并设置父对象为 this
    _timer = new QTimer(this);

    // 2. 设置时间间隔为 1000ms (1秒)
    _timer->setInterval(1000); // 1000ms = 1s
    ui->intervalLabel->setText("interval: " + QString::number(_timer->interval()) + "ms");

    // 3. 绑定信号槽:计时器timeout-->更新timeLabel内容
    connect(_timer, &QTimer::timeout, this, [this]()
    {
        QTime curTime = QTime::currentTime();
        QString curStr = curTime.toString("hh:mm:ss.zzz");
        this->ui->timeLabel->setText(curStr);
    });

    // 4. 绑定信号槽:点击start按钮,timer开始计时
    connect(ui->startButton, &QPushButton::clicked, _timer, [this]()
    {
        _timer->start(); // start()有重载,不能直接传地址
    });

    // 5. 绑定信号槽:点击stop按钮,timer停止计时,并且timeLabe显示停止信息
    connect(ui->stopButton, &QPushButton::clicked, _timer, &QTimer::stop);
    connect(ui->stopButton, &QPushButton::clicked, ui->timeLabel, [this]()
    {
        bool timerState = _timer->isActive();
        QString state = QVariant(timerState).toString();
        ui->timeLabel->setText("timer: " + state);
    });
}

MainWindow::~MainWindow()
{
    delete ui;
}

1.2 计时器精度设置

在处理多媒体或高频刷新界面时,需要手动调整定时器精度以平衡 CPU 占用率与时间准确度。Qt 提供三种精度枚举 (Qt::TimerType):

  • Qt::PreciseTimer:精确的毫秒级。尽最大努力准时触发,占用系统资源较高。
  • Qt::CoarseTimer:粗糙精度(默认值)。允许误差在 5% 范围内,适合绝大多数常规需求。
  • Qt::VeryCoarseTimer:非常粗糙。精度在 1 秒左右,系统资源消耗极低,适合后台心跳等低频任务。

精度 API 原型:

// 设置/获取当前定时器的精度
void QTimer::setTimerType(Qt::TimerType atype);
Qt::TimerType QTimer::timerType() const;

示例代码:1.1中的示例精度调整为Qt::PreciseTimer

mainwindow.cpp的构造函数中添加:

    // 6. 将定时器精度提升为最高配置(毫秒级)
    _timer->setTimerType(Qt::PreciseTimer);

1.3 单次触发 (Single Shot)

有些场景下,我们不需要定时器一直周期性执行,而是仅仅需要“延时执行某项任务一次”。QTimer 提供了单次触发模式(Single Shot)。开启此模式后,定时器在第一次触发 timeout() 后就会自动停止。

单次触发 API 原型:

// 开启/关闭单次触发模式 (true为仅触发一次,false为周期性触发)
void QTimer::setSingleShot(bool singleShot);
// 检查当前是否为单次触发模式
bool QTimer::isSingleShot() const;

示例代码:

1.2的基础上增加延时关闭按钮:点击按钮 fiveCloseButton 后,程序倒计时 5 秒,随后自动关闭窗口。

mainwindow.cpp的构造函数中添加:

    // 7. 绑定信号槽:点击 fiveCloseButton 测试单次触发 (5秒后关闭窗口)
    connect(ui->fiveCloseButton, &QPushButton::clicked, this, [this]()
    {
        // 7.1 界面先给出反馈,告诉用户即将关闭
        ui->timeLabel->setText("System will close automatically in 5 seconds...");

        // 7.2 禁用按钮,防止用户疯狂连点创建无数个定时器
        ui->fiveCloseButton->setEnabled(false);

        // 7.3 实例化一个专门用于延时的局部定时器
        QTimer* delayTimer = new QTimer(this);

        // 7.4 【核心】开启单次触发模式
        delayTimer->setSingleShot(true);

        // 7.5  绑定超时动作:时间一到,直接调用 MainWindow 的 close() 方法关闭窗口
        connect(delayTimer, &QTimer::timeout, this, &QMainWindow::close);

        // 7.6 启动定时器,延时5秒
        delayTimer->start(5000);
    });

1.3 补充:极简的单次延时方案(静态函数)

虽然通过 new QTimer() 配合 setSingleShot(true) 可以完美实现需求,但这会产生额外的对象管理代码。Qt 专门针对“单次延时任务”提供了一个高度封装的静态函数。如果你不需要在界面上给用户动态提示,只需一步操作即可完成。

静态函数API:

// 静态延时函数:内部自动创建并销毁定时器
// 参数1: 延时时间 (毫秒)
// 参数2: 接收信号的上下文对象
// 参数3: 时间到达后需要执行的槽函数
[static] void QTimer::singleShot(int msec, const QObject *receiver, const char *member);

示例代码:

上述 5 秒后关闭窗口的代码,若不需要更新 UI 提示,只需极简的一行代码:

// 5000ms 倒计时结束后,this 对象直接执行 close 槽函数
QTimer::singleShot(5000, this, &MainWindow::close);

若要执行多个步骤,可以用Lambda表达式(但要注意所有在Lambda表达式中的内容都会在延时结束后的一瞬间执行!):

QTimer::singleShot(5000, this,  [this]()
{
    // 在延时结束后,所有内容一瞬间一起执行完毕!
	...
    this->close();
});

在实际项目开发中,这种 QTimer::singleShot() 静态函数的写法,是处理“单次延时任务”的最优解!

posted @ 2026-05-24 17:09  学习笔记草稿存放账号  阅读(28)  评论(0)    收藏  举报