目录
Qt 绘制效率优化(分场景 + 实操方案,Linux/Windows 通用)
一、基础规则(必做,零代码改动 / 少量改动)
1. 严控重绘范围(最有效)
2. 绘制时机 & 信号槽优化
二、QWidget 原生绘制优化(paintEvent 场景)
1. 简化 paintEvent 内部逻辑
2. 双缓冲(解决闪烁 + 提速)
3. 图像绘制优化(图片 / 图标)
三、渲染引擎选型(核心提速:软件渲染 → 硬件加速)
1. 区分三大绘制体系
2. QGraphicsView 专项优化(图表、矢量图、大量图元)
3. Qt Quick (QML) 最优解(高帧率动画 / 滚动列表)
四、高级优化 & 避坑(大数据 / 曲线 / 工控常用)
1. 曲线 / 波形绘制(工控、示波器高频场景)
2. 关闭冗余渲染提示
3. 样式表(QSS)坑点
4. 多线程绘制规则
五、平台 & 编译优化(Linux 重点)
六、优化优先级总结(直接照做)
快速自查清单
示例:
一、核心原理回顾
二、完整示例(屏蔽自动重绘 + 离屏缓冲)
1. CustomWidget.h
2. CustomWidget.cpp(重点看注释里的 “屏蔽自动重绘” 部分)
3. main.cpp
三、关键屏蔽点说明
四、效果对比
五、额外避坑
Qt 绘制效率优化(分场景 + 实操方案,Linux/Windows 通用)
Qt 绘制卡顿、帧率低、CPU 高,核心根源:频繁重绘、绘制区域过大、冗余绘图、渲染方式选错、控件层级复杂。下面按「优先级从高到低」给出落地优化方案。
一、基础规则(必做,零代码改动 / 少量改动)
1. 严控重绘范围(最有效)
禁用全窗口重绘
- 不要调用
update()/repaint()无参形式(全局重绘) - 改用
update(rect)/update(region),只刷新变化区域 - 区别:
update()异步合并重绘(推荐),repaint()立即强制绘制(尽量少用)
- 不要调用
屏蔽不必要的自动重绘
- 自定义控件关闭
setAutoFillBackground(false),减少背景填充 - 动态数据控件:数据变更时只标记脏区域,不整页刷新
- 自定义控件关闭
重叠控件优化 多层控件重叠会多次绘制同一片区域,尽量减少层级、避免透明叠加。
2. 绘制时机 & 信号槽优化
高频数据(串口、定时器、网络)合并绘制请求短时间多次
update()会被 Qt 合并,但极端高频建议加防抖 / 节流:cpp
运行
// 节流:100ms 内只触发一次绘制 QTimer *m_drawTimer = new QTimer(this); m_drawTimer->setSingleShot(true); connect(m_drawTimer, &QTimer::timeout, this, &YourWidget::doUpdate); void onDataChanged() { if(!m_drawTimer->isActive()) m_drawTimer->start(100); } void doUpdate(){ update(); }定时器帧率适配 动画 / 实时绘制不要用
QTimer::setInterval(1),建议30~60fps(16ms/33ms),人眼无感知且大幅降负载。
二、QWidget 原生绘制优化(paintEvent 场景)
1. 简化 paintEvent 内部逻辑
绘图逻辑和业务逻辑分离
paintEvent只做绘制,禁止计算、文件 IO、网络、复杂判断,提前把数据预处理好。复用 QPainter、画笔、画刷、字体 不要在
paintEvent里频繁new QPen / QBrush / QFont,全局 / 成员变量缓存:cpp
运行
// 类成员,构造函数初始化一次 QPen m_pen; QBrush m_brush; QFont m_font; // paintEvent 直接使用,不重复创建 void paintEvent(QPaintEvent *e) { QPainter p(this); p.setPen(m_pen); p.setBrush(m_brush); ... }裁剪绘制区域 利用
QPaintEvent::rect()获取本次需要绘制的区域,只画该区域内内容:cpp
运行
void paintEvent(QPaintEvent *e) { QRect clipRect = e->rect(); QPainter p(this); p.setClipRect(clipRect); // 裁剪,超出区域不绘制 // 仅绘制 clipRect 范围内图形 }
2. 双缓冲(解决闪烁 + 提速)
Qt5/6 现代控件默认开启双缓冲,老式自定义控件、滚动控件必须手动开启。
- 全局开启(QWidget)
cpp
运行
setAttribute(Qt::WA_DoubleBuffer, true); // Qt5 // Qt6 统一使用: setAttribute(Qt::WA_OpaquePaintEvent, true); - 手动离屏缓冲(大数据 / 复杂图形最强方案) 用
QPixmap做离屏绘制,定时刷新 pixmap,而非实时绘制:cpp
运行
// 成员变量 QPixmap m_offscreenPix; // 数据变化时,一次性绘制到离屏图 void refreshData() { m_offscreenPix = QPixmap(size()); QPainter p(&m_offscreenPix); // 所有复杂绘制只执行一次 drawAllContent(p); update(); } // paintEvent 只做贴图,极快 void paintEvent(QPaintEvent *) { QPainter p(this); p.drawPixmap(0, 0, m_offscreenPix); }
3. 图像绘制优化(图片 / 图标)
- 大图提前缩放到目标尺寸并缓存,不要在
paintEvent里scaled() - 优先使用
QPixmap(屏幕绘制最优),少用QImage(CPU 格式,转换耗时) - 图标统一使用 Qt 资源文件
qrc,避免磁盘实时读取
三、渲染引擎选型(核心提速:软件渲染 → 硬件加速)
Qt 有三套渲染后端,复杂图形、动画、大数据图表优先切换硬件渲染。