上一篇文章提到在嵌入式运行时,自定义控件的整体重绘会消耗较多的CPU从而影响系统的实时性,因此考虑将调整控件的结构,把需要重绘的部件放到一块易于指定的区域内,从而达到每次重绘时只更新该区域来节省开销
查看update的定义了解到update本身支持只重绘指定的区域
void QWidget::update(const QRect &rect)
This is an overloaded function.
This version updates a rectangle rect inside the widget.
void QWidget::update(const QRegion &rgn)
This is an overloaded function.
This version repaints a region rgn inside the widget.
因此通过定义一个变量hasInitBackPixmap,初始值为false,在第一次paintEvent时绘制所有内容后置为true,在调用update时传入需要重绘的区域,此时则不再对不需要绘制的背景进行绘制
void gaugeColor::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(width()/2,height()/2);
int side=qMin(width(),height());
painter.scale(side/200.0,side/200.0);
if(!hasInitBackPixmap)
{
drawScale(&painter);
drawScaleNum(&painter);
hasInitBackPixmap=true;
}
drawNumericValue(&painter);
drawIndicator(&painter);
}
void gaugeColor::UpdateAngle(double newvalue)
{
m_value=newvalue;
int side=qMin(width(),height());
double k=side/200.0;
QRegion region(width()/2-64*k,height()/2-64*k,128*k,128*k,QRegion::Ellipse);
update(region);
}
上述代码的作用是只更新内部指针及数字显示部分所在圆形区域内,不再更新刻度尺等内容
调整后的效果如下图所示
另外,这样设计还有个小问题,是在窗口尺寸变化时,会引起部件的整体重绘,这样,由于hasInitBackPixmap已经为true,导致背景没有重新绘制产生下面的显示效果
查看paintEvent(QPaintEvent *)的帮助内容了解到QPaintEvent实际有传入重绘的区域:
The QPaintEvent class contains event parameters for paint events.
Paint events are sent to widgets that need to update themselves, for instance when part of a widget is exposed because a covering widget was moved.
The event contains a region() that needs to be updated, and a rect() that is the bounding rectangle of that region. Both are provided because many widgets cannot make much use of region(), and rect() can be much faster than region().boundingRect().
void gaugeColor::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(width()/2,height()/2);
int side=qMin(width(),height());
painter.scale(side/200.0,side/200.0);
if((!hasInitBackPixmap)||(event->rect().x()==0))
{
drawScale(&painter);
drawScaleNum(&painter);
hasInitBackPixmap=true;
}
drawNumericValue(&painter);
drawIndicator(&painter);
}