QT 自定义控件的重绘优化

上一篇文章提到在嵌入式运行时,自定义控件的整体重绘会消耗较多的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().

因此在paintEvent中作如下调整即可解决 该问题

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);
}

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值