QT PC 使用QLabel实现circle图片显示和图片旋转动画的功能

6 篇文章 0 订阅

一、实现图片circle显示

大概思路是:
先获得一个周边透明的圆形画布(安卓是画布,这里是painter),然后将要显示的图片画上去,这样获得了圆形的pixmap,将pixmap设置到QLabel上后OK。

void CircleLabel::setCirclePixmap(const QPixmap & circlepixmap)
{
    QPixmap pixmap(this->width(),this->height());
    pixmap.fill(Qt::transparent);
    QPainter painter(&pixmap);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    QPainterPath path;
    path.addEllipse(0, 0, this->width(),this->height());
    painter.setClipPath(path);
    painter.drawPixmap(0, 0, this->width(),this->height(), circlepixmap);
    this->setPixmap(pixmap);
}
二、旋转动画功能
1,一种是通过设置定时器不停地更新

如下代码:


    timerRotate_ = new QTimer(this);
    connect(timerRotate_, &QTimer::timeout, this, &SelfDialog::slotRotateTimeout);
    timerRotate_->start(100);
    
void SelfDialog::slotRotateTimeout()
{
    QMatrix matrix;
    matrix.rotate(180 * rotateStep_++);
    QPixmap orig = QPixmap(":/img/rotate_pic.png");
    QPixmap rotated = orig.transformed(matrix, Qt::SmoothTransformation);
    ui->labelRotate->setPixmap(rotated);
    rotateStep_ %= 2;
}

这种是在调用QLabel的地方设置一个定时器、一个角度值变量angle。比如定时每隔100ms执行一次,并且通过定时器的信号函数timeout触发的槽函数中执行,变化一次角度值变量angle,并且将angle值设置给QLabel中。
这种方式显然不够好,每个地方都要使用的话,代码冗余、耦合度太高(包括内容耦合、控制耦合等)、没有做到内聚(包括功能内聚、顺序内聚、通信内聚、过程内聚等)(触发条件需要使用定时器,增加了对定时器的控制代码,值需要在定时器中自己修改变化,然后还要单独的将值设置给QLabel)。
但是这里做到了自己控制刷新频率,灵活控制,并且可以通过合理降低频率达到性能的最大化。

2,第二种方法是使用属性动画QPropertyAnimation

在自定义的QLabel中添加如下代码:

    Q_PROPERTY(int rotation READ rotation WRITE setRotation)

    /**
     * @brief setRotation 为了使用属性动画QPropertyAnimation(this, "rotation")
     * @param rotation
     */
    void setRotation(int rotation);


    /**
     * @brief rotation 为了使用属性动画QPropertyAnimation(this, "rotation")
     * @return
     */
    int rotation() const;

使用时直接就是按照普通的属性动画的使用,代码如下:

    animation_ = new QPropertyAnimation(ui->labelLoadingIcon, "rotation");
    animation_->setDuration(4000);
    animation_->setStartValue(0);
    animation_->setEndValue(360);
    animation_->setLoopCount(-1); //旋转次数
//    connect(animation, SIGNAL(finished()), this, SLOT(onAnimation()));
    animation_->start(QAbstractAnimation::KeepWhenStopped);

这种方法使用起来要方便很多,代码也已经完全的按照属性动画使用,触发事件、属性值的变化等都已经由属性动画完成,需要做的只是在自定义的QLabel中添加这个属性刷新时的具体行为。
但是这种方法也有一个很大的缺陷,无法控制触发事件执行的频率,如果本身这个属性的刷新执行的操作是很消耗性能的,那么这样就很不划算

3,结合上面两种方法的优缺点,自己总结了第三种方法

这是在第二种方法的基础上优化而来的,解决了刷新频率的不可控问题,合理提高了性能。其实就是在第二种方法的基础上加了一个每隔100ms的刷新过滤,大于100ms执行刷新,小于则不作操作。

代码如下:

void CircleLabel::setRotation(int rotation)
{
    this->rotation_ = rotation;

    //perfect cpu usage
    if(!qTimeFilterRotate_.isValid()){
        qTimeFilterRotate_.start();
    }
    else{
        if(qTimeFilterRotate_.elapsed() > 100){
            qTimeFilterRotate_.restart();
        }
        else{
            return;
        }
    }
    //can use QMatrix to rotate
//    QMatrix matrix;
//    matrix.rotate(rotation/180 * 180);


    //use painter to rotate
    //让图片围绕中心旋转
    int imageWidth = pixmapOrigin_.width();
    int imageHeight = pixmapOrigin_ .height();
    QPixmap temp(pixmapOrigin_.size());
    temp.fill(Qt::transparent);
    QPainter  painter(&temp);
    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
    painter.translate(imageWidth / 2, imageHeight / 2);
    painter.rotate(rotation); //顺时针旋转90度
    painter.translate(-(imageWidth / 2), -(imageHeight / 2)); //使原点复原
    painter.drawPixmap(0, 0,   pixmapOrigin_);
    painter.end();


    this->setPixmap(temp);
}

通过第二、三种方法,测试了最近项目的具体性能参数对比,发现CPU使用率降了一个数量级,当然这个在具体项目具体执行的操作中优化程度各异。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值