Qt|高频率绘图导致闪烁问题

978 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情

之前的文章中我有讲述Qt的双缓存机制,但是并没有应用到实际的项目中,前几天的新做的需求,也就是如何实时绘制动态波形图。如果忘记了可以翻一翻前面的文章瞅一眼。

刷新频率过快导致图形绘制时页面出现闪烁的问题。

我也曾查阅了不少资料,很多码友们也遇到过相似的问题,大多数也是出现在动态绘制图形中,大概的功能就是用鼠标绘制图形(例如:矩形)在实时绘制时会遇到闪烁的问题。

其实,我想说一句,你都用到了绘图拖动等功能了,为什么不使用QGraphicsView这个专门绘图的架构呢?非要自己弄个双缓存来搞,想不透!

在讲解代码实现之前,我首先总结下Qt中双缓存的用法:就是将当前绘制的图形保存到QPixmap中,然后,在paintEvent中进行绘制。就这么简单。

使用过MFC架构的码友们都知道双缓存使用起来还挺麻烦,在Qt中几大简化了操作,方便了绘制。

绘图频率:每间隔50ms需要更新一次。

之前使用paintEvent绘制时,直接for循环遍历,并且存储到QPolygon中,最后进行一次性绘制。

图片.png

说实话,在paintEvent中进行for循环遍历,还是会消耗些时间,为什么我们不将绘图操作提取出来呢?直接进行绘制呢?

那么,进行如下修改:

1:定义临时画布

每次更新数据刷新时,都将绘制的内容重新赋值给QPixmap上。

这里,我们就需要定一个成员变量,用来实时存储最新的绘制数据,并对其进行初始化

.h中声明

QPixmap m_pixmapTemp; //定义:当前临时画布数据

.cpp中构造初始大小以及图形背景

m_pixmapTemp = QPixmap(400, 300); //当前绘制区域大小
//方法1:设置纯色背景
m_pixmapTemp.fill(Qt::white); //默认初始为白色
//方法2:设置图片背景
m_pixmapTemp.load("背景图片路径");

上述讲解了两种添加背景的方式:fillload哪种方式都是可以的。

2:将paintEvent的绘图操作提取到定时器刷新数据处理函数中。

QPainter painter(m_pixmapTemp);
/*
这里是具体的绘图操作
*/

以前在paintEvent绘制图形时,painter传入的都是this指针,在双缓存方法实现时,改成了临时画布作为绘图的父。接下来的具体绘图操作与在paintEvent中的方法一模一样。

3:在paintEvent绘制双缓存图形。

最后,将图形直接刷新到页面上。

void paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter->drawPixmap(this->rect(), m_pixmapTemp);
}

只需要像绘图普通图形一样绘制上去就可以了,是不是比MFC操作起来更简单方便呢?

到这里,运行程序时你会发现还有个奇怪的现象:在绘图时,之前绘制的图形并没有删除,还在原来的位置上保持着,这里,我们就需要在每次刷新时重新设置m_pixmapTemp,使之每次绘图时都是未进行绘图操作的样子。

这样就保证了每次更新临时画布区域图形时,都是实时变化的了。

如果大家有跟我一样的需求,实时绘制动态图操作,可以尝试一下哦!

我是中国好公民st,一名C++开发程序猿~