当前位置: 首页 > article >正文

现代Qt开发教程(新手篇)1.11——定时器

现代Qt开发教程新手篇1.11——定时器相关仓库仍然已经开源正在积极火热的建设之中欢迎各位大佬提Issue和PR链接地址https://github.com/Awesome-Embedded-Learning-Studio/Tutorial_AwesomeQt1. 前言为什么需要定时器说实话我第一次需要在程序里做「定时任务」的时候第一反应是写一个死循环里面加sleep()。结果试完就后悔了——界面卡死程序无响应任务管理器直接显示「未响应」。后来我才发现Qt 早就给我们准备了一个优雅的解决方案QTimer。它不仅能让你的程序在指定时间后执行某个任务还能周期性地重复执行而且最重要的是——它不会阻塞你的界面。想象一下这些场景你需要每秒更新一次时钟显示、需要延迟 3 秒后自动关闭提示框、需要每隔 100ms 检查一次传感器数据、需要做一个简单的动画效果。这些场景如果用sleep()或者系统原生定时器 API你会陷入跨平台兼容性的地狱。而 QTimer 把这一切都封装好了Windows、Linux、macOS 通用而且和 Qt 的事件循环完美集成。所以这一篇我们不玩虚的直接把 QTimer 的核心用法搞清楚。从最简单的单次定时到重复定时、高精度定时再到常见的坑我们都一一覆盖。2. 环境说明本文档基于 Qt 6.x 编写所有示例代码和 API 调用都已验证兼容 Qt 6.2 版本。定时器功能位于 Qt Core 模块中不需要额外链接 GUI 模块。你可以在命令行程序、GUI 程序甚至自定义的事件循环中使用它。3. 核心概念讲解3.1 QTimer 基础用法QTimer 的使用非常简单。它本质上是一个「倒计时器」倒计时结束后会发射一个timeout()信号。你只需要把这个信号连接到你的槽函数就可以实现定时执行任务。QTimer*timernewQTimer(this);// 设置定时间隔毫秒timer-setInterval(1000);// 1000 毫秒 1 秒// 连接 timeout 信号到你的槽connect(timer,QTimer::timeout,[](){qDebug()定时器触发了;});// 启动定时器timer-start();setInterval()设置的是两次触发之间的时间间隔单位是毫秒。start()启动定时器之后每隔指定的间隔timeout()信号就会被发射一次。当你不需要定时器时调用stop()即可停止。QTimer 还有一个方便的构造方式可以直接在启动时指定间隔QTimer*timernewQTimer(this);timer-start(1000);// 等价于 setInterval(1000) start()3.2 单次定时器有些时候你只需要「延迟执行一次」而不是周期性重复。QTimer 提供了setSingleShot(true)来实现这个功能QTimer*timernewQTimer(this);timer-setSingleShot(true);// 只触发一次timer-setInterval(3000);// 3 秒后触发connect(timer,QTimer::timeout,[](){qDebug()三秒后只执行这一次;});timer-start();设置单次模式后定时器只会在第一次触发后自动停止。这对于「延迟执行」的场景特别有用比如延迟关闭提示框、延迟加载资源等。Qt 还提供了一个更简洁的静态方法singleShot()非常适合一次性任务// 静态方法3 秒后执行 LambdaQTimer::singleShot(3000,[](){qDebug()三秒后执行;});// 也可以指定接收对象QTimer::singleShot(3000,this,[](){qDebug()在 this 对象的上下文中执行;});singleShot()的优势是你不需要自己管理定时器对象的生命周期Qt 会自动处理。这对于简单的延迟任务非常方便。3.3 重复定时器默认情况下QTimer 是重复触发的。这就是最常见的「周期性任务」场景QTimer*timernewQTimer(this);timer-setInterval(100);// 100 毫秒 0.1 秒intcounter0;connect(timer,QTimer::timeout,[](){counter;qDebug()Tickcounter;if(counter10){timer-stop();// 执行 10 次后停止qDebug()定时器停止;}});timer-start();重复定时器会一直运行直到你调用stop()或者定时器对象被销毁。需要注意的是定时器的间隔不是绝对精确的。如果事件循环很忙或者你的槽函数执行时间过长下一次触发可能会延迟。你可以通过isActive()检查定时器是否正在运行通过remainingTime()获取距离下一次触发的剩余时间if(timer-isActive()){qDebug()还有timer-remainingTime()毫秒触发;}3.4 高精度定时需求QTimer 的精度取决于操作系统和硬件。在大多数现代系统上精度通常在 10-20 毫秒左右。这对于一般的应用足够了但如果你需要更高精度的定时比如游戏循环、音频处理可能需要考虑其他方案。如果你需要测量时间间隔而不是定时触发应该使用QElapsedTimer而不是 QTimerQElapsedTimer elapsedTimer;elapsedTimer.start();// 执行一些操作QThread::msleep(500);qint64 elapsedelapsedTimer.elapsed();// 经过的毫秒数qDebug()经过了elapsed毫秒;// 也可以检查是否超时if(elapsedTimer.hasExpired(1000)){qDebug()已经超过 1 秒了;}QElapsedTimer是一个高精度的计时器用于测量时间间隔而不是定时触发事件。它通常用于性能测量、超时检测等场景。很多朋友会在这里搞混其实它们的区别很清楚QTimer 是「定时触发事件」会在指定时间后发射信号适合周期性任务QElapsedTimer 是「测量时间间隔」像一个秒表适合计算两个时刻之间的时间差。如果你要做一个「倒计时 10 秒」的功能应该用 QTimer因为它可以每秒触发一次更新显示而 QElapsedTimer 可以用来测量实际经过了多少时间作为辅助验证。如果你真的需要高精度的周期性定时比如游戏引擎的 60 FPS可以考虑结合QTimer和QElapsedTimerclassHighPrecisionTimer:publicQObject{Q_OBJECTpublic:HighPrecisionTimer(QObject*parentnullptr):QObject(parent){m_timer.setInterval(16);// 约 60 FPSconnect(m_timer,QTimer::timeout,this,HighPrecisionTimer::onTick);}voidstart(){m_elapsedTimer.start();m_timer.start();}privateslots:voidonTick(){qint64 elapsedm_elapsedTimer.restart();// elapsed 是上一帧到现在的实际时间// 可以用来做插值、补偿等updateFrame(elapsed);}private:QTimer m_timer;QElapsedTimer m_elapsedTimer;voidupdateFrame(qint64 deltaMs);};4. 踩坑预防清单定时器用起来很简单但有些坑真的会让你血压拉满。这里集中列几个最常见的。第一个坑是定时器对象被提前销毁。如果你在函数里new QTimer但没设置 parent函数结束后 timer 就成了野指针不但内存泄漏定时器还可能被意外销毁导致程序崩溃。正确的做法永远是new QTimer(this)让它随 parent 一起销毁或者手动管理生命周期。第二个坑是在错误的线程使用定时器。定时器属于哪个线程就在哪个线程触发。如果你在主线程创建了定时器却想在工作线程里用它那它根本不会触发或者触发后槽函数在错误的线程执行。解决办法是用moveToThread()把定时器移到目标线程或者直接在目标线程中创建。第三个坑是槽函数执行时间过长。如果你在timeout的槽函数里搞了一个耗时操作比如QThread::sleep(2)整个事件循环都会被阻塞界面卡死不说其他定时器也会变得不准。正确的做法是槽函数里只做标记耗时操作丢给工作线程去处理。第四个坑比较低级但真的很常见——忘记调用start()。你配置了间隔、连接了信号槽但就是忘了启动然后困惑为什么连接了信号槽却什么都没发生。记住配置完间隔后必须调用start()。接下来做一个代码填空练习补全以下代码实现一个每 500 毫秒打印一次计数、打印 5 次后停止的定时器QTimer*timernewQTimer(______);// 设置 parenttimer-______(500);// 设置间隔intcount0;connect(timer,QTimer::timeout,[](){count;qDebug()Count:count;if(count5){timer-______();// 停止定时器qDebug()Done!;}});timer-______();// 启动定时器提示需要填入的分别是this、setInterval、stop、start。参考答案如下QTimer*timernewQTimer(this);// 设置 parenttimer-setInterval(500);// 设置间隔intcount0;connect(timer,QTimer::timeout,[](){count;qDebug()Count:count;if(count5){timer-stop();// 停止定时器qDebug()Done!;}});timer-start();// 启动定时器再看一个调试挑战下面这段代码有什么问题为什么定时器可能不会按预期工作classMyClass:publicQObject{Q_OBJECTpublic:MyClass(){QTimer*timernewQTimer;timer-setInterval(1000);connect(timer,QTimer::timeout,this,MyClass::onTimeout);timer-start();}privateslots:voidonTimeout(){qDebug()Timeout!;}};问题出在定时器没有设置 parent会导致内存泄漏。更严重的是如果 MyClass 被销毁定时器仍然存在但this已经无效访问时会直接崩溃。正确写法是new QTimer(this)这样 MyClass 销毁时定时器也会一起被清理。5. 练习项目我们要做一个小型秒表程序功能不多但正好练手。创建一个命令行或简单 GUI 程序实现启动、暂停、重置秒表的功能每秒更新显示的当前时间格式MM:SS并且可以设置倒计时模式倒计时结束后发出提示。你的程序应该能正确响应启动、暂停、重置操作每秒准时更新显示倒计时到达零时能触发提示信号。代码结构清晰定时器管理合理没有内存泄漏或崩溃风险。提示几个方向用一个 QTimer 作为计时核心连接它的timeout信号到更新显示的槽需要维护一个「当前秒数」的状态变量暂停时停止计时器但不重置这个值倒计时模式可以在更新显示的槽里检查是否到达零QElapsedTimer 可以用来做高精度计时减少误差累积。6. 官方文档参考Qt 文档 · QTimer 类 – QTimer 的完整 API 参考包含所有信号、槽和属性说明Qt 文档 · QElapsedTimer 类 – 高精度计时器类用于测量时间间隔Qt 文档 · QObject::startTimer – 低级定时器 API直接使用定时器 ID注以上链接已通过互联网检索验证均可在 Qt 官方网站访问到这里就大功告成了。掌握了 QTimer你就可以在 Qt 程序里自由地实现各种定时任务这大大扩展了程序的交互能力和自动化程度。定时器是 Qt 开发中最常用的工具之一多练习几次你就会发现它的强大之处。下一节我们会讲插件系统看看如何让程序支持动态扩展。

相关文章:

现代Qt开发教程(新手篇)1.11——定时器

现代Qt开发教程(新手篇)1.11——定时器 相关仓库仍然已经开源,正在积极火热的建设之中,欢迎各位大佬提Issue和PR! 链接地址:https://github.com/Awesome-Embedded-Learning-Studio/Tutorial_AwesomeQt 1. 前…...

2026年5月阿里云上Hermes Agent/OpenClaw怎么部署?百炼token Plan配置详解

2026年5月阿里云上Hermes Agent/OpenClaw怎么部署?百炼token Plan配置详解。OpenClaw和Hermes Agent是什么?OpenClaw和Hermes Agent怎么部署?如何部署OpenClaw/Hermes Agent?2026年还在为部署OpenClaw和Hermes Agent到处找教程踩坑…...

CAN与CANopen技术:工业控制与汽车电子的核心通信方案

1. CAN与CANopen技术概述在嵌入式系统领域,控制器局域网(Controller Area Network,简称CAN)已经成为工业控制、汽车电子和物联网应用中不可或缺的通信技术。作为一名从事嵌入式开发十余年的工程师,我见证了CAN总线从汽…...

Windows系统xactengine2_7.dll文件丢失找不到无法启动程序解决

在使用电脑系统时经常会出现丢失找不到某些文件的情况,由于很多常用软件都是采用 Microsoft Visual Studio 编写的,所以这类软件的运行需要依赖微软Visual C运行库,比如像 QQ、迅雷、Adobe 软件等等,如果没有安装VC运行库或者安装…...

Windows系统xactengine2_8.dll文件丢失无法启动程序解决

在使用电脑系统时经常会出现丢失找不到某些文件的情况,由于很多常用软件都是采用 Microsoft Visual Studio 编写的,所以这类软件的运行需要依赖微软Visual C运行库,比如像 QQ、迅雷、Adobe 软件等等,如果没有安装VC运行库或者安装…...

xactengine2_10.dll文件丢失找不到无法启动程序解决

在使用电脑系统时经常会出现丢失找不到某些文件的情况,由于很多常用软件都是采用 Microsoft Visual Studio 编写的,所以这类软件的运行需要依赖微软Visual C运行库,比如像 QQ、迅雷、Adobe 软件等等,如果没有安装VC运行库或者安装…...

别只盯着dev环境!用Nacos配置中心为SpringBoot项目管理多环境(dev/test/pro)的完整实践

Nacos多环境配置管理:从开发到生产的SpringBoot实战指南 在微服务架构中,配置管理往往成为团队协作的痛点。想象这样一个场景:开发环境使用内存数据库,测试环境连接内网MySQL,而生产环境需要配置高可用集群。传统做法是…...

量子退火原理、应用与混合优化架构解析

1. 量子退火的核心原理与工作机制量子退火是一种受量子力学启发的优化算法,其核心思想是通过模拟量子系统的演化过程来寻找复杂优化问题的最优解。与传统模拟退火相比,量子退火引入了量子隧穿效应这一独特机制,使其能够突破经典优化算法面临的…...

通过Taotoken管理控制台精细化管控API Key的访问权限

通过Taotoken管理控制台精细化管控API Key的访问权限 1. 准备工作与登录控制台 在开始配置前,请确保您已拥有Taotoken平台的企业管理员或项目负责人账号权限。访问Taotoken官网,点击右上角登录按钮进入控制台。首次使用需完成企业邮箱验证和双因素认证…...

终极指南:使用TegraRcmGUI图形化工具实现Windows平台Switch破解注入

终极指南:使用TegraRcmGUI图形化工具实现Windows平台Switch破解注入 【免费下载链接】TegraRcmGUI C GUI for TegraRcmSmash (Fuse Gele exploit for Nintendo Switch) 项目地址: https://gitcode.com/gh_mirrors/te/TegraRcmGUI TegraRcmGUI是一款专为Windo…...

Nemotron-Cascade:强化学习驱动的模型级联推理框架

1. 项目概述:当推理模型遇上级联强化学习去年在优化一个多模态问答系统时,我遇到了一个典型困境:单一模型在简单问题上表现优异,但面对复杂推理任务时,准确率会断崖式下跌。这让我开始关注模型级联技术——而Nemotron-…...

从‘互相抄作业’到‘互相教’:Co-teaching如何让两个神经网络在噪声中共同成长

当神经网络学会"互批作业":Co-teaching对抗标签噪声的协同进化之道 在机器学习的世界里,数据质量往往决定着模型性能的上限。想象一下,如果课堂上40%的习题答案被故意写错,学生要如何避免被误导?这正是现实世…...

异步训练管道在机器人策略学习中的优化实践

1. 异步训练管道的核心价值在机器人策略学习领域,数据采集效率与训练速度一直是制约算法迭代的瓶颈。传统同步训练模式中,机器人需要在环境中完成完整回合(episode)后才能将数据传回中央服务器,这种"收集-训练-部…...

基于Tauri+React的跨平台桌面应用开发:架构设计与打包实战

1. 项目概述:WhereClaw 是什么? WhereClaw 是一个基于 Tauri 框架构建的跨平台桌面应用程序。简单来说,它提供了一个现代化的图形用户界面(GUI),而其核心功能则由一个名为 whereclaw-engine 的运行时引擎…...

MR-Search框架:元强化学习与自反思的智能优化

1. 项目概述:当强化学习遇上元学习与自反思 在强化学习领域,算法性能高度依赖于超参数的选择和策略架构的设计。传统方法往往需要大量试错或依赖专家经验,而MR-Search框架的创新之处在于将元强化学习(Meta-RL)与自反思…...

DuckDB向量搜索扩展:轻量级嵌入式AI检索实战指南

1. 项目概述:当DuckDB遇上向量搜索最近在折腾一些本地化的AI应用,比如个人知识库问答或者文档智能检索,发现一个挺有意思的痛点:数据量不大,但想快速实现一个带语义搜索的原型,传统方案要么太重&#xff08…...

Node.js+Express+MongoDB构建学生信息管理API全流程解析

1. 项目概述:一个学生信息管理API的诞生最近在整理过往项目时,翻到了一个挺有意思的“老伙计”——一个基于Node.js和Express构建的学生信息管理API。这个项目虽然结构清晰,但麻雀虽小,五脏俱全,涵盖了从数据建模、路由…...

魔兽争霸3终极优化工具:5分钟解锁高分辨率与高帧率体验

魔兽争霸3终极优化工具:5分钟解锁高分辨率与高帧率体验 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper WarcraftHelper是一款专为魔兽争霸…...

Kubernetes Operator实战:自主托管OpenClaw AI智能体的生产级部署指南

1. 项目概述:在Kubernetes上自主托管OpenClaw AI智能体如果你正在寻找一种方式,将OpenClaw AI智能体平台部署到自己的Kubernetes集群中,同时获得生产级别的安全性、可观测性和生命周期管理能力,那么openclaw-operator就是你需要的…...

新手必看!CTFshow Web1-20通关后,我总结的5个最实用的信息收集工具和技巧

从CTFshow Web1-20实战中提炼的5个高效信息收集方法论 刚接触CTF的新手常陷入一个困境:跟着教程一步步操作时能顺利解题,但面对全新靶场或真实环境却无从下手。这种差异源于缺乏系统化的信息收集思维。本文将分享我在通关CTFshow Web1-20系列后总结的五个…...

STM32平衡小车实战:MPU6050陀螺仪数据读取与中断配置避坑指南

STM32平衡小车实战:MPU6050陀螺仪数据读取与中断配置避坑指南 平衡小车作为嵌入式开发的经典项目,核心难点往往集中在传感器数据的精准获取与实时处理上。上周帮学弟调试他的毕业设计时,发现他的小车在静止状态下姿态角持续漂移,中…...

Qt6实战:用setGeometry和事件重写实现一个可拖拽、可缩放的自定义控件

Qt6实战:打造可拖拽、可缩放的Photoshop风格图层控件 在图形界面开发中,能够自由拖拽和调整大小的控件是提升用户体验的关键要素。想象一下Photoshop中的图层操作——那种流畅的拖拽感和精准的尺寸调整,正是我们今天要用Qt6实现的效果。本文将…...

从Orcad到Allegro:一个简单EEPROM模块的Cadence 17.4全流程保姆级教程

从Orcad到Allegro:一个简单EEPROM模块的Cadence 17.4全流程保姆级教程 在电子设计领域,Cadence 17.4套件以其强大的功能和专业的工作流程著称,但对于初学者来说,这套工具的学习曲线往往令人望而生畏。本文将以一个具体的EEPROM模块…...

保姆级教程:用Python+Pygame写个五子棋,并教你如何优化棋子的绘制和胜负判断逻辑

PythonPygame五子棋进阶:从图形优化到算法重构 五子棋作为一款经典策略游戏,其Python实现看似简单,但要让游戏体验和专业度达到商业级水准,需要解决诸多技术细节。本文将聚焦三个核心优化方向:棋子视觉效果提升、胜负判…...

C语言嵌入式OTA升级漏洞清单(2026年CVE-001~007实测复现):从签名绕过到Flash写保护失效的7大致命缺陷

更多请点击: https://intelliparadigm.com 第一章:C语言嵌入式OTA升级安全模型演进(2026版) 随着物联网设备规模化部署与零信任架构普及,嵌入式OTA升级已从“功能可用”转向“安全可信”。2026版安全模型在传统签名验…...

轻量级网页抓取工具pocketClaw:基于axios与cheerio的高效数据采集方案

1. 项目概述:一个轻量级、高可用的网页内容抓取工具最近在折腾一个需要聚合多个网站信息的个人项目,数据源五花八门,API要么没有,要么限制重重。手动复制粘贴效率太低,用现成的爬虫框架又感觉“杀鸡用牛刀”&#xff0…...

在Ubuntu 22.04上用Conda虚拟环境搞定Drake机器人库(附VSCode配置避坑)

在Ubuntu 22.04上用Conda虚拟环境搞定Drake机器人库(附VSCode配置避坑) 机器人开发领域,Drake作为MIT开源的多刚体动力学库,正成为学术界和工业界的热门选择。但许多开发者在Ubuntu系统上配置Drake时,总会遇到环境管理…...

MITS算法:动态采样优化PMI计算效率

1. MITS算法概述:当统计指标遇上动态采样在推荐系统和自然语言处理领域,我们常常需要衡量词语之间的关联强度。传统方法如点互信息(PMI)虽然直观,但面临数据稀疏和长尾分布的问题。MITS(Mutual Information…...

告别‘系统找不到指定的文件’:Windows下用MinGW搞定GCC和Make的完整配置流程

告别‘系统找不到指定的文件’:Windows下用MinGW搞定GCC和Make的完整配置流程 如果你在Windows上尝试编译C程序时,遇到过"gcc not found"或"系统找不到指定的文件"这类错误,这篇文章就是为你准备的。我们将从实际问题出发…...

如何轻松解锁鸣潮120FPS:WaveTools游戏优化完整指南

如何轻松解锁鸣潮120FPS:WaveTools游戏优化完整指南 【免费下载链接】WaveTools 🧰鸣潮工具箱 项目地址: https://gitcode.com/gh_mirrors/wa/WaveTools 还在为《鸣潮》的60FPS帧率限制而烦恼吗?你的高端显卡是否在游戏中无法发挥全部…...