QTimer必须依赖事件循环才能触发timeout()信号,子线程中需调用exec();setInterval()需stop()+start()才生效;singleShot()不可取消;精度模式影响定时准确性;父对象管理不当易导致崩溃。

QTimer 不是“开了就能准点跑”的独立线程,它完全依赖所属线程的事件循环 —— 没有 exec(),timeout() 信号永远不会发出。
QTimer 必须在有事件循环的线程里才能工作
你在控制台程序里用 QCoreApplication,就得调 a.exec();在 GUI 程序里,QApplication::exec() 已经帮你启动了主线程事件循环。如果在子线程中创建 QTimer,必须手动调用 QThread::exec(),否则定时器静默失效。
- 常见错误现象:
start(1000)后没任何输出,isActive()返回true,但timeout()从不触发 - 根本原因:线程没有运行事件循环,
QTimer的底层定时事件无法被分发 - 子线程正确写法:创建
QThread→ moveQTimer过去 → 在线程里调exec()(不能只 start() 线程就完事)
setInterval() 修改后必须 stop() + start() 才生效
setInterval() 不会热更新正在运行的定时器。直接改间隔再等下一次触发?不会按新值走 —— 它仍按旧间隔计时,直到你显式重启。
- 错误写法:
timer->setInterval(500);// 此时 timer 正在运行,间隔不变 - 正确写法:
timer->stop(); timer->setInterval(500); timer->start(); - 例外:用
start(int msec)重载时,它内部会先 stop 再设 interval 再 start,可一步到位
QTimer::singleShot() 是延迟执行,不是“轻量版 QTimer 对象”
QTimer::singleShot() 是静态函数,背后会自动创建、配置、启动并销毁一个一次性定时器。它不返回对象指针,也不能查状态、不能 stop、不能改间隔 —— 就是“扔进去,到点执行,完事”。需要中途取消?不行,得换成长生命周期的 QTimer* 实例。
- 适用场景:弹窗 3 秒后自动关闭、初始化后延时加载、异步回调前加固定延迟
- 不适用场景:倒计时 UI(需持续更新)、可暂停/恢复的定时任务、需根据条件动态调整延迟
- 注意:lambda 捕获的变量生命周期必须覆盖到执行时刻,否则 crash;建议用
QObject成员函数或显式传参
精度设置影响实际触发时机,尤其在低负载或高精度需求时
默认 Qt::CoarseTimer 允许 ±5% 误差,对 UI 刷新或轮询够用;但做音频同步、传感器采样或动画帧控,得切到 Qt::PreciseTimer。不过 Windows 上它依赖 timeSetEvent,频繁使用可能耗尽系统资源。
- 性能权衡:越精确,系统开销越大;
Qt::VeryCoarseTimer适合分钟级任务(如心跳上报),误差可达 500ms - 跨平台差异:Linux 上
PreciseTimer表现更稳;Windows 下若同时存在多个高精度定时器,可能互相干扰 - 零间隔定时器(
start(0))本质是“尽快执行”,常用于把耗时操作拆成小块防界面卡死,但它不是并发,仍是串行排队
真正容易被忽略的是:QTimer 的父对象管理机制。用 new QTimer(this) 时,父对象析构会自动 delete 定时器;但若用栈上对象(如 QTimer timer;),必须确保它的生命周期覆盖整个定时过程,否则 timeout() 信号发向已销毁对象,直接 crash —— 这类问题在 lambda 槽函数里尤其隐蔽。











