Qt QWidget自定义绘制paintEvent导致的递归循环
#Qt QWidget自定义绘制 paintEvent导致的递归循环
最近在一个项目中遇到一个界面卡顿问题,现已解决,记录如下:
问题描述:
点击界面某个控件时,界面卡顿,调试发现父控件重载的paintEvent一直被循环调用,导致界面卡顿
原因:
在自定义控件QWidget中,重载的paintEvent函数中调用了子控件QLabel的update()函数。
void CustomWidget::paintEvent(QPaintEvent *event)
{
label->update();
}
当子控件Qlabel 调用update重绘时,默认下会重绘背景,也就是QWidget的paintEvent会被调用,于是导致了递归循环
解决方法:
//给QLabel指定“WA_OpaquePaintEvent”属性,避免透明背景
label->setAttribute(Qt::WA_OpaquePaintEvent);
设置WA_OpaquePaintEvent 属性可以简单理解为,让本控件变得不透明,这样下层的控件图层不需要重绘来实现本控件的透明效果。
Qt帮助文档对WA_OpaquePaintEvent属性的描述如下:
Indicates that the widget paints all its pixels when it receives a paint event. Thus, it is not required for operations like updating, resizing, scrolling and focus changes to erase the widget before generating paint events. The use of WA_OpaquePaintEvent provides a small optimization by helping to reduce flicker on systems that do not support double buffering and avoiding computational cycles necessary to erase the background prior to painting. Note: Unlike WA_NoSystemBackground, WA_OpaquePaintEvent makes an effort to avoid transparent window backgrounds. This flag is set or cleared by the widget’s author.
WA_OpaquePaintEvent 属性指示控件当接收到绘制事件时,绘制每一个像素,它的使用提供了一个小的优化,在不支持双缓冲系统的系统上减少了闪烁,并且避免了在绘制之前擦除背景的计算周期。
可见该属性在控件、窗体重绘时避免了重绘背景、擦除本控件的消耗,带来性能的提升。
当然如果需要控件实现 “透明” 的效果就不要指定该属性,同时不要试图在自身的paintEvent中刷新或重绘任何上层控件