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 的生命周期和状态流转分为三个关键节点:
-
实例化 (
new QTimer):定时器被创建,但处于停止状态。通过传入父对象指针,可以利用 Qt 的对象树机制实现内存自动回收。 -
设置间隔 (
setInterval):仅仅是配置了定时器的属性(每次触发的时间间隔),并不会触发计时。- 特殊机制:如果将间隔设为
0,在调用.start()后定时器不会立刻疯狂触发,而是在窗口系统的事件队列处理完毕、处于空闲状态时才会触发。
- 特殊机制:如果将间隔设为
-
调用启动方法 (
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 中通过 startButton 和 stopButton 控制定时器,并在 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()静态函数的写法,是处理“单次延时任务”的最优解!

浙公网安备 33010602011771号