1. 工业控制系统选型Qt的底层逻辑1.1 为什么工业场景偏爱Qt而不是Web那一套做过工业现场的人都有一个共识:车间里的东西和互联网产品完全是两个世界。互联网可以容忍偶尔的卡顿、刷新、重连,但一条产线上的上位机如果界面卡死三秒钟,可能意味着一批工件报废,甚至触发安全联锁。这就是为什么在工业控制系统(Industrial Control System,ICS)这个领域,Qt依然是2026年最稳的选择之一。Qt的核心优势在于它是原生编译的C++框架,直接跑在操作系统之上,没有浏览器内核那一层开销。你写的一个按钮响应,从事件触发到界面刷新,延迟通常在毫秒级,而基于Web的方案即使做了再多优化,中间隔着渲染引擎和通信层,抖动很难压到同样水平。工业现场对确定性的要求远高于对界面炫酷的要求,这一点决定了技术选型的基调。另一个关键点是Qt的跨平台能力。一套代码可以编译到Windows、Linux,甚至一些实时操作系统上。很多工控机跑的是裁剪过的Linux,而工程师的开发机是Windows,Qt能让同一份工程在两边都能编译运行,省掉了大量适配工作。再加上Qt对串口、网络、多线程、数据库这些工业常用模块都有成熟封装,等于把底层脏活累活都替你干了。1.2 2026年Qt版本与授权该怎么选到2026年,Qt的版本迭代已经相当成熟,主流稳定分支基本围绕Qt 6.x系列展开。选版本这件事,我的建议是:不要追最新,要追最稳。工业项目生命周期动辄五到十年,你选了一个刚发布两三个月的小版本,后面遇到bug修复周期长,会很被动。通常选择已经发布一年以上、社区反馈充分的LTS(长期支持)版本更靠谱。授权方面是很多团队容易踩坑的地方。Qt有开源版和商业版两条线,开源版走LGPL协议,商业版提供更完整的模块和官方支持。工业项目如果涉及闭源分发,LGPL下你需要确保用户能替换Qt库(动态链接通常可以满足),这一点在法务层面要提前确认清楚,别等产品交付了才发现授权有问题。我的经验是,涉及核心商业机密的项目,直接上商业授权,省心;内部工具或对分发没要求的,开源版完全够用。提示:授权问题一定要在项目立项阶段就找法务过一遍,不要等到代码写完再补,返工成本极高。1.3 工业控制系统的核心需求拆解在动手写代码之前,得先把这类系统的需求理清楚。工业控制系统通常包含几个绕不开的模块:实时数据采集(从PLC、传感器、板卡读数据)、设备控制下发(写寄存器、发指令)、状态监控与报警(阈值判断、报警推送)、数据存储与追溯(历史曲线、报表)、人机交互界面(HMI)。这几个模块对技术的要求各不相同,采集和控制要求低延迟高可靠,存储要求不丢数据,界面要求响应流畅。把这些需求映射到Qt上,就对应到不同的技术点:采集用QSerialPort或网络Socket,控制下发要注意线程安全,报警用信号槽机制做事件驱动,存储用QSqlDatabase或直接写文件,界面用QWidget或QML。理清这层映射关系,后面的架构设计就有了骨架。2. 项目架构设计与模块拆分实操2.1 分层架构:把界面和业务彻底分开工业项目最容易犯的错误,就是把所有逻辑都塞进界面类里。刚开始看着挺快,等到要加一个设备、改一个协议,你会发现牵一发动全身。正确的做法是分层,我一般分成四层:通信层、数据层、业务逻辑层、界面层。通信层负责和硬件打交道,把原始字节流解析成有意义的数据结构;数据层负责缓存和持久化,维护当前设备状态;业务逻辑层做报警判断、联动控制、流程调度;界面层只负责展示和接收用户操作。层与层之间通过明确定义的接口通信,界面层绝对不能直接去读串口。这样分的好处是,当硬件协议变了,你只改通信层;当界面要换风格,你只动界面层。我做过一个项目,前期用QWidget做的界面,后来客户要求换成更现代的QML风格,因为分层清晰,界面层整个重写只花了两周,业务逻辑一行没动。2.2 线程模型:别让界面卡死是第一原则Qt里界面刷新必须在主线程(GUI线程),而数据采集、网络通信这些耗时操作必须放到子线程,否则界面就会卡。这是Qt开发工业系统的铁律。常见的做法是每个设备或每类任务开一个QThread,用信号槽跨线程传递数据。这里有个细节很多人搞错:信号槽的跨线程连接默认是队列连接(QueuedConnection),数据会被拷贝到目标线程的事件队列里。这意味着如果你采集频率很高,比如每毫秒一次,事件队列会堆积,反而拖慢系统。这时候要么降低传递频率(攒批再发),要么用共享内存加锁的方式,但加锁又要小心死锁。我的经验是,采集线程内部做数据聚合,比如每50毫秒打包一次发给界面,既保证流畅又不丢实时性。// 采集线程中攒批发送的简化示例 void AcquisitionThread::run() { QVector<SamplePoint> batch; while (m_running) { batch.append(readOnePoint()); if (batch.size() >= 50) { emit batchReady(batch); // 跨线程信号 batch.clear(); } QThread::msleep(1); } }2.3 通信协议解析的通用化设计工业现场协议五花八门,Modbus、自定义串口协议、TCP私有协议都有。如果每个协议都写一套解析代码,维护起来是灾难。我的做法是抽象一个协议解析接口,把"收字节、组帧、校验、解析字段"这几步标准化,具体协议实现这个接口。组帧是最容易出问题的地方。串口数据是流式的,你收到的可能是半帧、一帧半、或者粘包。常见做法是用状态机逐字节扫描,找到帧头后按长度字段读取,再做校验。校验方式(CRC16、累加和、异或)也要可配置。这套东西写一次,后面接新设备就是填配置的事。协议要素常见实现注意事项帧头识别固定字节序列注意帧头字节可能出现在数据区长度字段固定位置读取要防越界,设最大帧长校验方式CRC16/累加和校验失败要丢弃整帧而非部分超时处理定时器重置半帧超时要清空缓冲2.4 数据存储:实时库和历史库分开工业系统对数据存储有两个截然不同的需求:一是当前值的快速读写(界面要实时显示),二是历史数据的长期保存(追溯和报表)。这两者用同一套存储会互相拖累。我的方案是内存里维护一份当前值快照(用QHash或自定义结构),界面直接读内存;历史数据异步写入数据库或文件。数据库选型上,SQLite适合单机小规模,数据量大或者要多机共享就上时序数据库。但工业现场经常没条件装复杂数据库,这时候直接写二进制文件加索引也是可行的,关键是写入要异步,别阻塞采集线程。我见过有项目在采集回调里直接写数据库,结果数据库一卡,整个采集就停了,这是大忌。3. 核心功能模块的落地实现3.1 实时数据采集模块的完整实现采集模块是整个系统的心脏,它的稳定性直接决定项目成败。我一般把它设计成一个独立的类,内部管理一个QThread,对外暴露start、stop和dataReady信号。启动时打开设备(串口或Socket),进入循环读取,读到完整帧就解析并通过信号发出。串口配置这块有几个参数必须配对:波特率、数据位、停止位、校验位,任何一个和硬件不一致都收不到正确数据。调试阶段建议先用串口助手确认硬件在正常发数据,再接入自己的程序,能省掉大量排查时间。网络采集则要注意设置合理的超时和重连机制,工业网络偶尔抖动是常态,程序不能因为一次断连就崩。// 串口采集初始化要点 QSerialPort* port = new QSerialPort(this); port->setPortName("COM3"); port->setBaudRate(QSerialPort::Baud115200); port->setDataBits(QSerialPort::Data8); port->setStopBits(QSerialPort::OneStop); port->setParity(QSerialPort::NoParity); if (!port->open(QIODevice::ReadWrite)) { // 记录日志并触发报警,不要静默失败 } connect(port, &QSerialPort::readyRead, this, &Collector::onDataArrived);注意:串口打开失败一定要有明确的日志和界面提示,工业现场最怕的就是"程序在跑但没数据",操作员根本不知道哪里出了问题。3.2 报警与事件处理机制报警模块的设计要点是去重、分级、可追溯。去重是指同一个报警在恢复之前不要反复推送,否则操作员会被刷屏;分级是指不同严重程度的报警要有不同的处理策略,比如紧急报警要弹窗加声音,一般报警只记录;可追溯是指每次报警的产生、确认、恢复都要有时间戳和操作人记录。实现上用状态机比较合适:每个报警点有正常、触发、确认、恢复几个状态,状态迁移时发信号。界面订阅这些信号更新报警列表。声音报警要注意别用阻塞式播放,用异步播放或者系统提示音,否则会卡界面。我踩过的坑是报警声音文件太大,每次播放都卡一下,后来换成短促的提示音就顺了。3.3 界面响应优化与大数据量渲染工业界面经常要显示大量实时数据,比如几百个点的曲线、上千行的表格。如果处理不当,界面会明显卡顿。曲线绘制建议用QCustomPlot或QtCharts,并且只保留可视区域的数据点,历史数据滚动出去就丢弃。表格用QTableView配合自定义Model,不要用QTableWidget逐格设置,后者在数据量大时性能差一个数量级。刷新频率也要控制。人眼对超过30帧每秒的刷新其实感知不明显,工业界面20帧左右就足够流畅。用一个定时器统一驱动界面刷新,而不是每个数据变化都触发重绘,能大幅降低CPU占用。我做过对比,统一刷新后CPU占用从40%降到了15%左右。3.4 配置化设计:让现场调试不再改代码工业项目交付后,现场经常要调整参数:设备地址变了、量程改了、报警阈值调了。如果每次都要改代码重新编译,那维护成本高得离谱。所以配置化设计是必须的。把设备列表、通信参数、点位定义、报警阈值都放到配置文件(JSON或XML)里,程序启动时读取。更进一步,可以做一个配置界面,让现场工程师自己改。但要注意配置的校验,比如波特率只能填标准值,地址不能重复。配置文件建议带版本号,升级程序时能识别旧配置并做迁移。我见过因为配置文件格式变了导致老现场全部无法启动的事故,加个版本兼容逻辑就能避免。4. 现场部署与常见问题排查4.1 打包发布与依赖处理Qt程序发布最头疼的是依赖库。Windows下需要带上对应的Qt DLL,还要注意编译器运行库(MSVC或MinGW)。用windeployqt工具能自动拷贝大部分依赖,但它不一定全,尤其是你用了第三方库的时候。我的做法是先在干净的虚拟机上跑一遍,缺什么补什么,把依赖清单固定下来。Linux下相对简单,但要注意glibc版本兼容。开发机上新,目标机老,可能跑不起来。稳妥的做法是在和目标机同版本的系统上编译,或者用容器固定编译环境。发布包建议做成自解压或安装脚本,把程序、依赖、配置、文档一起打包,现场人员双击就能装。4.2 常见问题速查表现场问题千奇百怪,但高频的就那么几类。我整理了一份速查表,基本能覆盖八成情况。现象可能原因排查方向界面卡死主线程做了耗时操作检查是否有同步IO或死循环收不到数据串口参数错/线序错用串口助手先验证硬件数据乱码字节序或编码问题确认大小端和字符集内存持续增长对象未释放/信号未断开用工具查泄漏点程序启动慢初始化阻塞/加载大文件异步初始化,加启动画面报警不触发阈值判断逻辑错打印中间值定位4.3 长时间运行的稳定性保障工业系统要求7x24小时运行,稳定性是硬指标。几个关键措施:一是所有可能失败的操作都要有异常处理和重试;二是定期检查资源占用,内存、句柄、线程数异常要能自愈或报警;三是日志要完整,出问题时能回溯。日志建议分级(调试、信息、警告、错误),并且按天或按大小滚动,别让日志文件把磁盘写满。关键操作和异常一定要记日志,但高频的采集数据不要每条都记,否则日志会爆炸。我一般只在数据异常或状态变化时记录。4.4 现场调试的实战心得最后分享几条现场调试的经验。第一,永远带一个能独立验证硬件的工具,比如串口助手、网络调试助手,出问题时先确认是硬件还是软件。第二,改配置前先备份,现场环境复杂,改错了能快速回退。第三,和现场操作员多聊,他们最清楚什么现象在什么时候出现,这些信息比你自己瞎猜有用得多。第四,留一个隐藏的诊断入口,比如按某个组合键弹出诊断窗口,能看到原始数据和内部状态,排查问题时能救命。工业控制系统的开发,技术只是一部分,更多的是对现场的理解和对细节的把控。Qt给了你一套足够强大的工具,但怎么用好,靠的是一个个项目踩出来的经验。我个人的体会是,前期在架构和配置化上多花的时间,后期都会以数倍的调试效率还回来。
1. 工业控制系统选型Qt的底层逻辑1.1 为什么工业场景偏爱Qt而不是Web那一套做过工业现场的人都有一个共识:车间里的东西和互联网产品完全是两个世界。互联网可以容忍偶尔的卡顿、刷新、重连,但一条产线上的上位机如果界面卡死三秒钟,可能意味着一批工件报废,甚至触发安全联锁。这就是为什么在工业控制系统(Industrial Control System,ICS)这个领域,Qt依然是2026年最稳的选择之一。Qt的核心优势在于它是原生编译的C++框架,直接跑在操作系统之上,没有浏览器内核那一层开销。你写的一个按钮响应,从事件触发到界面刷新,延迟通常在毫秒级,而基于Web的方案即使做了再多优化,中间隔着渲染引擎和通信层,抖动很难压到同样水平。工业现场对确定性的要求远高于对界面炫酷的要求,这一点决定了技术选型的基调。另一个关键点是Qt的跨平台能力。一套代码可以编译到Windows、Linux,甚至一些实时操作系统上。很多工控机跑的是裁剪过的Linux,而工程师的开发机是Windows,Qt能让同一份工程在两边都能编译运行,省掉了大量适配工作。再加上Qt对串口、网络、多线程、数据库这些工业常用模块都有成熟封装,等于把底层脏活累活都替你干了。1.2 2026年Qt版本与授权该怎么选到2026年,Qt的版本迭代已经相当成熟,主流稳定分支基本围绕Qt 6.x系列展开。选版本这件事,我的建议是:不要追最新,要追最稳。工业项目生命周期动辄五到十年,你选了一个刚发布两三个月的小版本,后面遇到bug修复周期长,会很被动。通常选择已经发布一年以上、社区反馈充分的LTS(长期支持)版本更靠谱。授权方面是很多团队容易踩坑的地方。Qt有开源版和商业版两条线,开源版走LGPL协议,商业版提供更完整的模块和官方支持。工业项目如果涉及闭源分发,LGPL下你需要确保用户能替换Qt库(动态链接通常可以满足),这一点在法务层面要提前确认清楚,别等产品交付了才发现授权有问题。我的经验是,涉及核心商业机密的项目,直接上商业授权,省心;内部工具或对分发没要求的,开源版完全够用。提示:授权问题一定要在项目立项阶段就找法务过一遍,不要等到代码写完再补,返工成本极高。1.3 工业控制系统的核心需求拆解在动手写代码之前,得先把这类系统的需求理清楚。工业控制系统通常包含几个绕不开的模块:实时数据采集(从PLC、传感器、板卡读数据)、设备控制下发(写寄存器、发指令)、状态监控与报警(阈值判断、报警推送)、数据存储与追溯(历史曲线、报表)、人机交互界面(HMI)。这几个模块对技术的要求各不相同,采集和控制要求低延迟高可靠,存储要求不丢数据,界面要求响应流畅。把这些需求映射到Qt上,就对应到不同的技术点:采集用QSerialPort或网络Socket,控制下发要注意线程安全,报警用信号槽机制做事件驱动,存储用QSqlDatabase或直接写文件,界面用QWidget或QML。理清这层映射关系,后面的架构设计就有了骨架。2. 项目架构设计与模块拆分实操2.1 分层架构:把界面和业务彻底分开工业项目最容易犯的错误,就是把所有逻辑都塞进界面类里。刚开始看着挺快,等到要加一个设备、改一个协议,你会发现牵一发动全身。正确的做法是分层,我一般分成四层:通信层、数据层、业务逻辑层、界面层。通信层负责和硬件打交道,把原始字节流解析成有意义的数据结构;数据层负责缓存和持久化,维护当前设备状态;业务逻辑层做报警判断、联动控制、流程调度;界面层只负责展示和接收用户操作。层与层之间通过明确定义的接口通信,界面层绝对不能直接去读串口。这样分的好处是,当硬件协议变了,你只改通信层;当界面要换风格,你只动界面层。我做过一个项目,前期用QWidget做的界面,后来客户要求换成更现代的QML风格,因为分层清晰,界面层整个重写只花了两周,业务逻辑一行没动。2.2 线程模型:别让界面卡死是第一原则Qt里界面刷新必须在主线程(GUI线程),而数据采集、网络通信这些耗时操作必须放到子线程,否则界面就会卡。这是Qt开发工业系统的铁律。常见的做法是每个设备或每类任务开一个QThread,用信号槽跨线程传递数据。这里有个细节很多人搞错:信号槽的跨线程连接默认是队列连接(QueuedConnection),数据会被拷贝到目标线程的事件队列里。这意味着如果你采集频率很高,比如每毫秒一次,事件队列会堆积,反而拖慢系统。这时候要么降低传递频率(攒批再发),要么用共享内存加锁的方式,但加锁又要小心死锁。我的经验是,采集线程内部做数据聚合,比如每50毫秒打包一次发给界面,既保证流畅又不丢实时性。// 采集线程中攒批发送的简化示例 void AcquisitionThread::run() { QVector<SamplePoint> batch; while (m_running) { batch.append(readOnePoint()); if (batch.size() >= 50) { emit batchReady(batch); // 跨线程信号 batch.clear(); } QThread::msleep(1); } }2.3 通信协议解析的通用化设计工业现场协议五花八门,Modbus、自定义串口协议、TCP私有协议都有。如果每个协议都写一套解析代码,维护起来是灾难。我的做法是抽象一个协议解析接口,把"收字节、组帧、校验、解析字段"这几步标准化,具体协议实现这个接口。组帧是最容易出问题的地方。串口数据是流式的,你收到的可能是半帧、一帧半、或者粘包。常见做法是用状态机逐字节扫描,找到帧头后按长度字段读取,再做校验。校验方式(CRC16、累加和、异或)也要可配置。这套东西写一次,后面接新设备就是填配置的事。协议要素常见实现注意事项帧头识别固定字节序列注意帧头字节可能出现在数据区长度字段固定位置读取要防越界,设最大帧长校验方式CRC16/累加和校验失败要丢弃整帧而非部分超时处理定时器重置半帧超时要清空缓冲2.4 数据存储:实时库和历史库分开工业系统对数据存储有两个截然不同的需求:一是当前值的快速读写(界面要实时显示),二是历史数据的长期保存(追溯和报表)。这两者用同一套存储会互相拖累。我的方案是内存里维护一份当前值快照(用QHash或自定义结构),界面直接读内存;历史数据异步写入数据库或文件。数据库选型上,SQLite适合单机小规模,数据量大或者要多机共享就上时序数据库。但工业现场经常没条件装复杂数据库,这时候直接写二进制文件加索引也是可行的,关键是写入要异步,别阻塞采集线程。我见过有项目在采集回调里直接写数据库,结果数据库一卡,整个采集就停了,这是大忌。3. 核心功能模块的落地实现3.1 实时数据采集模块的完整实现采集模块是整个系统的心脏,它的稳定性直接决定项目成败。我一般把它设计成一个独立的类,内部管理一个QThread,对外暴露start、stop和dataReady信号。启动时打开设备(串口或Socket),进入循环读取,读到完整帧就解析并通过信号发出。串口配置这块有几个参数必须配对:波特率、数据位、停止位、校验位,任何一个和硬件不一致都收不到正确数据。调试阶段建议先用串口助手确认硬件在正常发数据,再接入自己的程序,能省掉大量排查时间。网络采集则要注意设置合理的超时和重连机制,工业网络偶尔抖动是常态,程序不能因为一次断连就崩。// 串口采集初始化要点 QSerialPort* port = new QSerialPort(this); port->setPortName("COM3"); port->setBaudRate(QSerialPort::Baud115200); port->setDataBits(QSerialPort::Data8); port->setStopBits(QSerialPort::OneStop); port->setParity(QSerialPort::NoParity); if (!port->open(QIODevice::ReadWrite)) { // 记录日志并触发报警,不要静默失败 } connect(port, &QSerialPort::readyRead, this, &Collector::onDataArrived);注意:串口打开失败一定要有明确的日志和界面提示,工业现场最怕的就是"程序在跑但没数据",操作员根本不知道哪里出了问题。3.2 报警与事件处理机制报警模块的设计要点是去重、分级、可追溯。去重是指同一个报警在恢复之前不要反复推送,否则操作员会被刷屏;分级是指不同严重程度的报警要有不同的处理策略,比如紧急报警要弹窗加声音,一般报警只记录;可追溯是指每次报警的产生、确认、恢复都要有时间戳和操作人记录。实现上用状态机比较合适:每个报警点有正常、触发、确认、恢复几个状态,状态迁移时发信号。界面订阅这些信号更新报警列表。声音报警要注意别用阻塞式播放,用异步播放或者系统提示音,否则会卡界面。我踩过的坑是报警声音文件太大,每次播放都卡一下,后来换成短促的提示音就顺了。3.3 界面响应优化与大数据量渲染工业界面经常要显示大量实时数据,比如几百个点的曲线、上千行的表格。如果处理不当,界面会明显卡顿。曲线绘制建议用QCustomPlot或QtCharts,并且只保留可视区域的数据点,历史数据滚动出去就丢弃。表格用QTableView配合自定义Model,不要用QTableWidget逐格设置,后者在数据量大时性能差一个数量级。刷新频率也要控制。人眼对超过30帧每秒的刷新其实感知不明显,工业界面20帧左右就足够流畅。用一个定时器统一驱动界面刷新,而不是每个数据变化都触发重绘,能大幅降低CPU占用。我做过对比,统一刷新后CPU占用从40%降到了15%左右。3.4 配置化设计:让现场调试不再改代码工业项目交付后,现场经常要调整参数:设备地址变了、量程改了、报警阈值调了。如果每次都要改代码重新编译,那维护成本高得离谱。所以配置化设计是必须的。把设备列表、通信参数、点位定义、报警阈值都放到配置文件(JSON或XML)里,程序启动时读取。更进一步,可以做一个配置界面,让现场工程师自己改。但要注意配置的校验,比如波特率只能填标准值,地址不能重复。配置文件建议带版本号,升级程序时能识别旧配置并做迁移。我见过因为配置文件格式变了导致老现场全部无法启动的事故,加个版本兼容逻辑就能避免。4. 现场部署与常见问题排查4.1 打包发布与依赖处理Qt程序发布最头疼的是依赖库。Windows下需要带上对应的Qt DLL,还要注意编译器运行库(MSVC或MinGW)。用windeployqt工具能自动拷贝大部分依赖,但它不一定全,尤其是你用了第三方库的时候。我的做法是先在干净的虚拟机上跑一遍,缺什么补什么,把依赖清单固定下来。Linux下相对简单,但要注意glibc版本兼容。开发机上新,目标机老,可能跑不起来。稳妥的做法是在和目标机同版本的系统上编译,或者用容器固定编译环境。发布包建议做成自解压或安装脚本,把程序、依赖、配置、文档一起打包,现场人员双击就能装。4.2 常见问题速查表现场问题千奇百怪,但高频的就那么几类。我整理了一份速查表,基本能覆盖八成情况。现象可能原因排查方向界面卡死主线程做了耗时操作检查是否有同步IO或死循环收不到数据串口参数错/线序错用串口助手先验证硬件数据乱码字节序或编码问题确认大小端和字符集内存持续增长对象未释放/信号未断开用工具查泄漏点程序启动慢初始化阻塞/加载大文件异步初始化,加启动画面报警不触发阈值判断逻辑错打印中间值定位4.3 长时间运行的稳定性保障工业系统要求7x24小时运行,稳定性是硬指标。几个关键措施:一是所有可能失败的操作都要有异常处理和重试;二是定期检查资源占用,内存、句柄、线程数异常要能自愈或报警;三是日志要完整,出问题时能回溯。日志建议分级(调试、信息、警告、错误),并且按天或按大小滚动,别让日志文件把磁盘写满。关键操作和异常一定要记日志,但高频的采集数据不要每条都记,否则日志会爆炸。我一般只在数据异常或状态变化时记录。4.4 现场调试的实战心得最后分享几条现场调试的经验。第一,永远带一个能独立验证硬件的工具,比如串口助手、网络调试助手,出问题时先确认是硬件还是软件。第二,改配置前先备份,现场环境复杂,改错了能快速回退。第三,和现场操作员多聊,他们最清楚什么现象在什么时候出现,这些信息比你自己瞎猜有用得多。第四,留一个隐藏的诊断入口,比如按某个组合键弹出诊断窗口,能看到原始数据和内部状态,排查问题时能救命。工业控制系统的开发,技术只是一部分,更多的是对现场的理解和对细节的把控。Qt给了你一套足够强大的工具,但怎么用好,靠的是一个个项目踩出来的经验。我个人的体会是,前期在架构和配置化上多花的时间,后期都会以数倍的调试效率还回来。