1. 工业上位机需求分析与Qt技术选型
工业上位机不是“把设备数据画到屏幕上”这么简单。它通常运行在产线工控机、机柜触摸屏或中控室工作站上,向下通过串口、Modbus TCP、OPC UA、CAN 或私有 TCP 协议连接 PLC、仪表、运动控制器和采集模块,向上承担设备监控、参数配置、报警记录、数据追溯,并可能对接 MES、数据库或历史库。技术选型一旦定错,后期会在刷新性能、触摸交互、多语言、部署体积和长期维护上付出代价。因此第一步不是写代码,而是把真实场景拆成可判断的需求,再决定用 Qt Widgets 还是 Qt Quick/QML。
从四个真实场景提取需求
设备监控关注“现在怎么样”。典型对象是 8~32 台设备的状态、温度、压力、转速、产量。关键指标是刷新周期与数据量:例如 20 台设备、每台 30 个测点,共 600 个变量,若要求 200 ms 刷新一次,则每秒需处理约 3000 次变量更新。这类需求的核心不是界面多炫,而是数据采集与 UI 刷新解耦,避免通信线程阻塞界面。
参数配置关注“怎么改、改得对不对”。工业参数往往有量程、单位、步长、互锁和权限:如温度设定范围 0~250 ℃、步长 0.1 ℃,只有工程师权限可写,写入前需二次确认,写入后要回读校验。这里需要表单校验、权限控制和写值确认机制,而不是简单绑定一个输入框。
报警记录关注“什么时候出了什么事”。报警应包含时间戳、设备、点位、报警级别、触发值、确认状态和确认人。报警不是普通列表,它要求实时插入、按级别着色、声光提示、历史查询和确认留痕。若报警量达到每秒数十条,界面必须支持批量刷新与分页查询。
数据追溯关注“过去发生了什么”。需要按时间段、设备、批次查询历史曲线和报表,数据可能来自 SQLite、MySQL、PostgreSQL 或时序库。追溯界面通常查询频率低、数据量大,适合表格与曲线组合,而不是高频动画。
功能需求与非功能需求要分开写
功能需求回答“系统做什么”:设备连接与断线重连、实时监控、参数读写、报警产生与确认、历史查询、报表导出、用户登录与权限。非功能需求回答“做到什么程度”:刷新周期、启动时间、内存占用、部署方式、可维护性、可扩展性、触摸操作、多语言和断电恢复。工业现场尤其要明确三点:一是通信异常时界面不能卡死;二是参数写入必须可校验、可回读;三是报警与历史数据不能丢。建议在需求阶段就写出可验证指标,例如“界面主线程单次阻塞不超过 50 ms”“断线后 3 s 内自动重连”“历史查询 10 万条记录 2 s 内返回首页”。
Qt Widgets、Qt Quick 与 QML 的适用边界
Qt Widgets 基于 C++ 原生控件,适合密集表格、树形结构、菜单、对话框、多窗口和传统桌面操作。它的优势是成熟、稳定、控件丰富、与 C++ 结合直接,适合参数配置、报警列表、历史查询、报表这类“信息密度高、交互偏鼠标键盘”的界面。缺点是默认视觉偏传统,触摸动画和自定义皮肤成本较高。
Qt Quick/QML 基于场景图和声明式 UI,适合触摸屏、动画、状态切换、卡片式监控和大屏展示。它的优势是界面现代、触摸友好、动画流畅、易于做自适应布局。缺点是复杂表格和树控件不如 Widgets 成熟,C++ 与 QML 之间需要清晰的模型暴露,过度在 QML 中写业务逻辑会导致维护困难。
在工业 HMI 中,常见做法不是二选一,而是混合:用 Qt Widgets 做配置、报警、追溯等重表单界面,用 Qt Quick 做设备总览、触摸操作和动画看板;或者统一用 Qt Quick,但把数据模型、通信和业务规则放在 C++ 层。若项目是传统机柜工控机、以鼠标键盘为主、表格多、交付周期紧,优先 Qt Widgets;若项目是触摸屏、大屏、强调视觉反馈和动画,优先 Qt Quick;若团队 C++ 强而 QML 弱,不要为了“好看”强行全 QML。
确定技术栈与项目骨架
结合上述判断,一个可落地的工业上位机骨架通常分为四层。第一层是通信层:用 QSerialPort、QTcpSocket 或第三方 OPC UA 库连接设备,运行在独立 QThread 中,负责收发、解析、重连和超时。第二层是数据层:把采集到的变量写入线程安全的数据中心,例如以“设备 ID + 点位 ID”为键的 QHash,配合 QReadWriteLock 或信号槽跨线程投递;历史数据写入 SQLite 或 PostgreSQL。第三层是业务层:报警判断、参数校验、权限控制、批次追溯,全部用 C++ 实现,不依赖具体界面。第四层是界面层:Widgets 负责配置、报警、追溯,Quick 负责总览和触摸看板,两者通过同一套 C++ 模型获取数据。
项目目录可按以下方式组织,便于后续 30 章逐步扩展:
IndustrialHMI/
├── core/ # 数据中心、报警引擎、权限、配置
├── comm/ # 串口/TCP/Modbus/OPC UA 通信
├── storage/ # SQLite/历史库、报表导出
├── ui_widgets/ # 参数配置、报警列表、历史查询
├── ui_quick/ # 设备总览、触摸看板
├── models/ # 暴露给 QML 的 C++ 模型
└── main.cpp # 组装通信、业务与界面