嵌入式系统中,能否使用QML不取决于是否有GPU,而在于是否具备OpenGLES2.0+、EGL、DRM/KMS支持及稳定驱动。QtWidgets适合低内存、无GPU或仅2D加速场景,强调稳定与轻量;QML/QtQuick则需硬件与驱动支持,适用于触控、动画、可视化等体验型界面。选型应优先评估硬件条件、内存、分辨率与团队能力,而非"新旧"之争。最佳实践是C++做核心逻辑,QML负责界面呈现,混合架构兼顾性能与体验。
1. 先纠正一个前提
"嵌入式设备基本都有 GPU"这句话只对了一半。
更准确的表述是:
中高端嵌入式 Linux SoC 通常有图形加速单元,但是否能支撑 QML,取决于它是否支持 OpenGL ES 2.0+、EGL、DRM/KMS,以及 BSP 是否提供了稳定用户态驱动。
有 GPU ≠ 能跑 Qt Quick。
有 GPU 但只有 2D blit 加速、没有 OpenGL ES、没有 EGL device integration,QML 依然会卡、花屏、起不来。
2. 本质差异:不是"新旧"之争,而是渲染模型不同
| 维度 | Qt Widgets | QML / Qt Quick |
|---|---|---|
| 渲染模型 | CPU 软件光栅化(QPainter / Raster) | GPU Scene Graph(Qt 6 走 RHI:OpenGL ES / Vulkan / D3D / Metal / Software) |
| 编程模型 | 命令式 C++ | 声明式 QML + C++ 后端 |
| 适用界面 | 表单、表格、配置、工控后台 | 触控、动画、转场、数据可视化 |
| 内存占用 | 低且稳定 | 较高,含 QML 引擎 / JS / Scene Graph |
| 启动开销 | 小 | 有 QML 解析/编译开销,可用 qmlcachegen 缓解 |
| 多窗口/桌面式 UI | 强 | 弱(嵌入式通常单窗全屏) |
| 驱动依赖 | LinuxFB 也能跑 | EGLFS/Wayland + GPU 驱动健康才能发挥价值 |
Qt 官方文档也明确:
复杂 UI 下 Widgets 始终走软件后端;需要动画、平滑滚动、缩放、渲染特效、3D 时,应使用 Qt Quick,而这通常需要 GPU 加速。
3. 嵌入式场景下的硬筛选条件
先过硬件与系统条件,再谈体验。
3.1 选 Qt Widgets 的硬条件
-
RAM ≤ 256~512 MB
-
无 GPU / 只有 2D 加速 / LinuxFB 平台
-
BSP 没有稳定 EGL/DRM 支持
-
界面以按钮、表单、表格、参数配置为主
-
要求启动快、内存可控、十年不崩
-
团队是 C++ 工程师,不懂 JS / 前端状态管理
-
产品是工业控制台、测试仪器、PLC HMI、医疗设备参数页
特点:
Widgets 在 EGLFS 下也能跑,但本质是 CPU 渲染成图片,再作为纹理合成。
3.2 选 QML / Qt Quick 的硬条件
-
SoC 有 GPU,且支持 OpenGL ES 2.0+
-
BSP 提供 EGL + DRM/KMS,EGLFS 或 Wayland 正常
-
RAM ≥ 512 MB,理想 1 GB 以上
-
屏幕 ≥ 5~7 寸,分辨率 800x480 / 1280x800 / 1920x1080
-
需要滑动列表、页面转场、仪表盘、曲线、视频叠加、触摸手势
-
UI 由设计师产出,需要皮肤/主题/高 DPI 适配
-
产品是车载 HMI、智能家居屏、高端工业 HMI、医疗设备触控界面
特点:
QML 不是"更好看一点",而是把 UI 合成、变换、动画、透明度、缩放交给 GPU。
4. 什么时候"有 GPU 也别用 QML"
这是嵌入式里最容易踩的坑:
-
GPU 很弱:Cortex-A7 + 老 Mali-400,却要做 1080p 动画
-
BSP 驱动闭源、PowerVR / 国产 GPU,社区资料少
-
Qt 版本升级后 QML 行为变化,项目无法回归
-
高频数据刷新:每秒几千点采样、密集表格、SCADA 点位
-
业务逻辑写在 QML/JS 里,导致状态难追、性能失控
这类项目即使"有 GPU",也常出现:
QML 示例能跑,业务一复杂就掉帧;
Widgets 丑但稳,QML 漂亮但交付前开始救火。
规则:
QML 的底线不是"有 GPU",而是"GPU 驱动可靠 + 场景适配 + 团队懂边界"。
5. 工程上最稳的架构:C++ 做脑,QML 做脸
无论选哪个,嵌入式 Qt 的正确分层都是:
硬件 / 驱动 / BSP
↓
C++ 业务层:通信、协议、数据采集、状态机、存储
↓
Model / Context / QObject 暴露接口
↓
UI 层:Widgets 或 QML
QML 项目铁律
-
复杂算法、协议解析、线程、文件、数据库:C++
-
QML 只做:布局、状态、动画、绑定、页面切换
-
JS 只做:轻量转换、UI 逻辑
-
禁止:在 QML 里写大段业务逻辑、轮询、定时重算、网络解析
Qt 官方也建议:写声明式 QML,尽量减少 JavaScript 使用。
6. 混合架构:不是妥协,是工业现实
很多量产嵌入式产品采用:
-
主界面:QML(仪表盘、主页、动画、触摸交互)
-
配置/日志/高级参数/调试页:Widgets 或 QWidget 嵌入
-
视频/相机/OpenGL 层:C++ + QOpenGL / DRM / V4L2
-
核心控制:纯 C++
实现方式:
-
QQuickView/Window做主界面 -
C++ 用
qmlRegisterType/setContextProperty暴露数据 -
复杂表格用 C++ Model(
QAbstractTableModel) -
历史项目迁移时:新页面用 QML,老页面保留 Widgets
注意:
EGLFS 下单进程通常只有一个原生窗口,直接把 QWidget 和 QQuickWindow 混成两个顶层窗口会出问题;混合要用 QQuickWidget或在 Wayland 多窗口环境里设计。
7. 决策树
有没有稳定 OpenGL ES + EGL + DRM?
├─ 否
│ └─ Qt Widgets
├─ 是
│ ├─ UI 主要是表单/表格/配置/长期稳定?
│ │ └─ Qt Widgets
│ ├─ UI 需要动画/触摸/转场/可视化?
│ │ ├─ 团队懂 C++/QML 边界?
│ │ │ └─ QML + C++ 后端
│ │ └─ 不懂 → Widgets 或先培训再上 QML
│ └─ 既有炫酷界面又有密集工业配置?
│ └─ QML 主界面 + C++ Model + 局部 Widgets
8. 一句话总结
**Widgets 是"先把界面跑起来并且别出事";
QML 是"在硬件和驱动都到位时,把界面体验做出来"。**
嵌入式选型顺序应该是:
-
看 SoC 和 BSP
-
看 RAM / 分辨率 / 帧率
-
看 UI 类型(工具型 or 体验型)
-
看团队能力
-
最后才看"QML 新不新、Widgets 老不老"