技术选型:为什么笔者的CCIMXDesktop选择了Qt6而不是Qt5作为GUI开发框架
前言
有人询问笔者,为什么不使用Qt5而是Qt6作为开发框架?笔者计划梳理一下理由,顺便分享一下Qt5和Qt6之间的小区别。
Qt6支持RHI抽象后端渲染
Qt6重构了我们对渲染管线重构,之前实际上对渲染后端的支持非常的有限,Qt6对 OpenGL、Vulkan、Direct3D、Metal 等做统一抽象,而不是单单只有Qt5的OpenGL 和 FrameBuffer。
Qt6对绘图,事件传递上做了更好的优化
事件传递
在过去的Qt5中,传递事件需要经过:输入设备驱动 → QPA(Qt Platform Abstraction) → QApplication 事件队列 → 各个窗口对象 → 最终目标控件这几个步骤,可以看到这里存在非常多的事件转发,触发了不少的对象拷贝工作。
现在,我们是
- 采用懒包装的能力,直接传递原始事件数据(例如
QPointerEvent
),避免 Qt5 时代对QMouseEvent
/QTouchEvent
的多次包装与拷贝。 - 对于高频输入(如手写、快速滑动),Qt6 会合并短时间内的相邻事件,减少事件循环压力。这样的话就防止重复的触发事件callback
- Qt6 在 QPA 层就能过滤掉不可见/禁用控件的事件,而不是像 Qt5 那样先进入应用层再丢弃。
- CPU 占用下降明显,触控延迟降低(尤其在 ARM Cortex-A7/A9 这种 1GHz 左右的处理器上,UI响应更顺畅)。
QPainter
- 减少状态切换成本:Qt5 中频繁调用
setPen
、setBrush
会导致底层多次状态机切换,Qt6 在绘制管线中引入了状态缓存,避免重复设置相同状态。 - 更智能的脏矩形(Dirty Region)计算:Qt6 优化了需要重绘的区域计算,能更准确地确定哪部分需要重绘,而不是大面积无效刷新。
- 抗锯齿与混合模式优化:Qt6 对软件渲染路径中使用的
QImage
绘制算法做了 SIMD 优化(在 ARM NEON / x86 SSE 上都有提升),减少纯 CPU 绘制的耗时。
窗口合成(Compositing)效率优化
在Qt6,更多的评估了懒拷贝 + 多评估的算法,防止频繁的重新绘制buffer
- 分层更新:如果一个窗口或 QQuickItem 的内容没变,就不会重新合成那一层。
- 零拷贝路径:在硬件支持的情况下(如 DRM/KMS + EGL),Qt6 会直接让 GPU 将图层送到显示控制器(Overlay),跳过 CPU 内存拷贝。
- 减少 FBO(Frame Buffer Object)切换:Qt6 RHI 可以缓存并复用 Framebuffer,避免 Qt5 时代频繁的 FBO 创建/销毁。
嵌入式收益:在有 GPU 的平台上,合成延迟下降,CPU/GPU 协作更高效;在纯软件渲染平台,Qt6 也减少了多余的像素拷贝。
一句话说完:
Qt6 在事件传递上减少了中间包装和无效分发,在 QPainter 上改进了脏矩形计算和状态缓存,在窗口合成上实现了分层更新和零拷贝,这些优化让嵌入式平台在 CPU 占用、内存带宽和 UI 延迟上都有显著改善,比 Qt5 更适合资源受限的设备。
其实笔者还有一个原因
Qt5支持的C++有点太老了,比如说笔者现在习惯的是C++17,使用的GCC编译器集中在GCC13 ~ GCC15左右,笔者使用新的C++编译器去编译老Qt就会发现大量的不兼容的问题,很是一个麻烦的事情,因此这也是笔者为什么最后抛弃了Qt5,一方面,简单的小程序在Qt5中笔者使用QPropertyAnimation就会出现非常明显的卡顿(FPS目测在5~6左右,对,默认的示例程序就卡成筛子了),Qt6就完全好很多,看不出卡顿(大概在15FPS以上)
BTW,笔者的设计比较粗糙,基本上是开启Animation后立马启动QElapsedTimer测量paintEvent的调用次数,基本上得到的结论如上。