Qt桌面白板工具其三(解决半透明桌面画布刷新透明像素时产生耗时,导致的画笔卡顿问题)

本文讲述了作者在实现桌面画板过程中遇到的卡顿问题,通过深入分析发现是由于频繁的paintEvent和父窗口的半透明刷新造成的。作者最终通过使用区域刷新功能,只更新绘制部分,解决了卡顿问题并提升了性能。
摘要由CSDN通过智能技术生成

一、问题
前两篇文章写了很多有关桌面画板的实现方法,这个过程中,画笔的卡顿问题还是无法彻底解决。
先简单回顾一下我实现桌面画板的逻辑;
1.父窗口:一个透明窗口,通过设置带有透明度的QColor bg_color,以及在paintEvent中整个窗口刷透明颜色。通过切换bg_color的alpha通道,来实现画布的穿透效果或透明绘制效果,没有透明度的白色则为白板。

	QPainter painter(this);
    painter.fillRect(this->rect(), bg_color);

2.绘图子窗口,布局在父窗口内,完全透明,主要负责实际产生的QImage图像的刷新。
在该窗口中重载了相应的鼠标函数,通过搜集一系列的鼠标经过点,来对QImage进行绘制。有关QPainter绘制QImage的内容不再赘述。最后,在该类的paintEvent中,将整张QImage刷新上去,实现绘制效果。
为了实现实时的刷新,有两种思路。
(1)在moveEvent搜集点,绘制QImage的同时,update()触发paintEvent
(2)通过定时器,每30ms刷新一次update,将QImage绘制上去。这基本上是主流相机的图片帧帧率了
在我电脑上统计,每一秒会触发900余次moveevent,相当于搜集了900多个点。在进行临近点的过滤后,仍然有500余点,即会触发500次update(因为update不是实时刷新,内部有优化,所以实际上不是这么多。)这样的话,paintEvent过于频繁,在内部产生的耗时会造成moveEvent触发过少,导致绘图卡顿,是恶性循环。所以,第二种方法较好。

可即便如此,采用定时器触发,在触发定时时,仍会造成moveEvent的阻塞,造成规律性的绘图卡顿,即期望通过鼠标绘制一条圆滑曲线,结果线段会规律地出现折线。

二、问题查找过程
通过繁琐的检测耗时,我发现在moveEvent中,对QImage实时绘制线段,其实是极低的,因为绘制(刷新)区域仅线段所在的范围;
而在paintEvent中,将一整张图绘制上窗口时,耗时比较严重,有25ms左右。
我又对比了QPixmap和QImage之间的效率,发现相差不大,又在窗口内塞入了一个QLabel,想要另辟蹊径,结果都不理想
最终,我发现了造成25ms延时的问题所在:子窗口触发paintEvent的同时,父窗口也会触发paintEvent,即我每一次刷新我的QImage图像时,都还会让父窗口刷一遍半透明像素颜色…
通过检测耗时,确定就是该处造成的原因

三、问题分析与解决办法
如果,父窗口不是透明的,速度立马上来了,曲线变得圆滑,简直完美!可无奈,我需要半透明画板,因为我要实现桌面画板,对ppt啊啥的进行实时标注嘛。
这就很让人头疼,因为尝试了其他半透明窗口的实现,都不理想。于是我想到了,干脆不要父窗口了,在子窗口中,半透明像素的刷新和QImage的显示,同步在paintEvent中做……
结果就是,跟之前是一毛一样的效果,都是卡!
而如果强行把半透明刷新和QImage拆开,可能会造成一些奇怪的问题,比如单次绘制之后,因为没有触发半透明刷新,导致窗口直接穿透了的bug

需要明确,半透明像素颜色刷新,是必须的。但我思考了下,其实不需要全部刷新,即不需要整个窗口区域的刷新。qt的update非常友好地提供了区域刷新的功能,即

update(QRect(x,x,x,x));

刷新的时候,我直接传入一个计算好的矩形,即可避免上述25ms耗时的产生。
是不是茅塞顿开?hh
不过,我还是采用了上述在子窗口中同时刷新半透明像素点和QImage的方法,然后将父窗口直接完全透明处理了。
那,剩下的就是刷新区域的计算问题了。
刷新半透明像素点,本质上也是刷新QImage,所以QRect的区域,在我们moveEvent中采集点的过程中,实时去计算,目的是将“本次update的线段”都包含在QRect中。
因为考虑线宽的问题,实际上QRect还要再往外扩一下,详细代码就不贴了。
因为update传递了坐标,所以系统优化的时候,不会平白无故忽略了某一次,造成有其中一次线段不显示的情况。

至此,这个困扰我依旧的问题终于解决。效果嘛,算是比较流畅了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值