在 paintEvent 中绘制文本,首次正常,后续 update() 触发重绘时,旧文本未清除导致重叠:
void MyWidget::paintEvent(QPaintEvent *event) {
QPainter painter(this);
for (int i = 0; i < statListString.count(); ++i) {
painter.drawText(0, 90 + 16 * i, statListString.at(i));
}
}
→ 
Qt 默认不自动擦除背景。paintEvent 仅在当前脏矩形区域绘制,未绘制区域保留像素。文本绘制不覆盖背景,导致旧像素残留。
void MyWidget::paintEvent(QPaintEvent *event) {
QPainter painter(this);
// 1. 擦除整个控件区域(或仅脏矩形 event->rect())
painter.fillRect(rect(), palette().window()); // 使用调色板背景色
// painter.eraseRect(event->rect()); // 仅擦除脏区
// 2. 绘制新内容
for (int i = 0; i < statListString.count(); ++i) {
painter.drawText(0, 90 + 16 * i, statListString.at(i));
}
}
MyWidget::MyWidget(QWidget *parent) : QWidget(parent) {
setAttribute(Qt::WA_OpaquePaintEvent); // 标记不透明,Qt 自动填充背景
// 或 setAutoFillBackground(true); 配合 palette 设置
}
配合 setPalette() 设置背景色可避免闪烁。
void MyWidget::paintEvent(QPaintEvent *event) {
static QPixmap cache; // 缓存绘制结果
if (cache.isNull() || cache.size() != size()) {
cache = QPixmap(size());
}
QPainter cachePainter(&cache);
cachePainter.fillRect(rect(), Qt::white);
for (int i = 0; i < statListString.count(); ++i) {
cachePainter.drawText(0, 90 + 16 * i, statListString.at(i));
}
QPainter widgetPainter(this);
widgetPainter.drawPixmap(0, 0, cache);
}
| 方案 | 性能 | 闪烁风险 | 适用场景 |
|---|---|---|---|
| 手动 fillRect | 高 | 低 | 简单绘制、高频刷新 |
| WA_OpaquePaintEvent | 高 | 低 | 纯色背景、标准控件 |
| QPixmap 缓存 | 中(首次开销大) | 无 | 复杂绘制、抗锯齿文本 |
WA_OpaquePaintEvent + setAutoFillBackground(true)QPixmap 离屏渲染paintEvent 中做耗时计算,预计算好几何数据QStyleOption 适配主题样式