自学内容网 自学内容网

VS+Qt插件,动态加速旋转齿轮的实现。


前言

在实际开发中,我们可以使某些小控件“运动”起来。这样可以使得”一动不动“的软件框架看起来更有”生机“。在Qt中有一个动画类很好用,下面是笔者根据QPropertyAnimation类设计出的一个可以旋转运动的齿轮。

请添加图片描述


一、准备

1.齿轮图片

我们需要一张齿轮的图片,图片复杂或者简单根据需求就行,建议图片要透明背景的。

2.编译环境

本文用到的是VS2017+Qt插件。本文代码涉及到的内容并不复杂,因此不是特别久远的版本都能够实现。

二、主要代码

1.静态图片的实现

我们可以以QGraphicsView作为控件载体,在QGraphicsScene上实现:

QGraphicsScene* pScene = new QGraphicsScene(this);
m_pUi->m_pPreGraphicsView->setRenderHint(QPainter::Antialiasing);
m_pUi->m_pPreGraphicsView->setScene(pScene);

将QPixmap贴图在QGraphicsPixmapItem上:

QPixmap pixmap("图片路径.png");
QGraphicsPixmapItem* m_pPixmapItem = new QGraphicsPixmapItem(pixmap);
m_pPixmapItem->setPos(x,y);//x,y为图片位置的坐标
pScene->addItem(m_pPixmapItem);//加载静态图片

至此,一张静态的图片完成。

2.动态匀速旋转图片的实现

我们需要重写QGraphicsPixmapItem

#include <QApplication>
#include <QGraphicsPixmapItem>
#include <QPropertyAnimation>

class ZAnimatedPixmapItem : public QObject, public QGraphicsPixmapItem
{    
Q_OBJECT
public:
explicit ZAnimatedPixmapItem(const QPixmap& pixmap);
virtual ~ZAnimatedPixmapItem();
private:
QPropertyAnimation *pAnimation = nullptr;
}
ZAnimatedPixmapItem::ZAnimatedPixmapItem(const QPixmap& pixmap)
 : QGraphicsPixmapItem(pixmap)
 {
 this->setPixmap(pixmap);
 this->setTransformOriginPoint(this->boundingRect().center());
 pAnimation = new QPropertyAnimation(this, "rotation");
 pAnimation->setDuration(3000);//设置动画时间为3秒
 pAnimation->setEasingCurve(QEasingCurve::Linear);//设置匀速转动
 pAnimation->setStartValue(0);
 pAnimation->setEndValue(360);
 pAnimation->setLoopCount(-1);//设置成-1是将该动画设置成无限循环
 pAnimation->start();
 }

至此一个匀速转动效果的动画实现了。适用于无限匀速转动齿轮的需求。

3.动态加速度旋转图片的实现

假如现在有更深一层的需求,需要通过某个事件触发动画开始以及动画结束,如果突然就匀速旋转或者急停,动画效果难免有些生硬。这个时候我们可以引入加速度和减速度:

 pAnimation->setEasingCurve(QEasingCurve::InQuad);//设置加速转动
 pAnimation->setEasingCurve(QEasingCurve::OutQuad);//设置减速转动

如果直接冒然将加速替换匀速是不可取的,这样的后果是在一个新周期开始时动画旋转速度是0,然后到动画结束最快,然后速度突然降为0,周而复始。
为了让动画显示更具观赏性,我们需要在动画开始事件触发时的第一个周期,动画加速旋转。第一个周期结束后,动画匀速旋转,在触发了动画关闭事件后的下一个周期,动画开始减速旋转直到周期结束。

因此,我们需要保证在动画每次完成一轮后都会触发一次事件,用来观察下一个动画中期齿轮应该进行的动画。

class ZAnimatedPixmapItem : public QObject, public QGraphicsPixmapItem
{    
Q_OBJECT
public:
explicit ZAnimatedPixmapItem(const QPixmap& pixmap);
virtual ~ZAnimatedPixmapItem();
void StartAnimation();
    void StopAnimation();
    int nStatus = 0;//齿轮的运动状态,由旋转事件决定
    int completedLoops = 0;//周期结束后下一个周期做什么的判断依据
    int runflag = 0;//是否在进行动画

private slots:
    void onAnimationFinished();

private:
QPropertyAnimation *pAnimation = nullptr;
}
ZAnimatedPixmapItem::ZAnimatedPixmapItem(const QPixmap& pixmap)
 : QGraphicsPixmapItem(pixmap)
 {
 this->setPixmap(pixmap);
 this->setTransformOriginPoint(this->boundingRect().center());
 pAnimation = new QPropertyAnimation(this, "rotation");
 pAnimation->setStartValue(0);
 pAnimation->setEndValue(360);
    pAnimation->setLoopCount(1);//每完成一个周期都需要进行判断,因此只能将转动周期设置成1
    QObject::connect(pAnimation, &QPropertyAnimation::finished, this, &ZAnimatedPixmapItem::onAnimationFinished);
 }
 
void ZAnimatedPixmapItem::StartAnimation()
{
    nStatus = 1;
    if (0 == completedLoops && 0 == runflag)
    {
        completedLoops = 1;
        pAnimation->setDuration(3000);
        pAnimation->setEasingCurve(QEasingCurve::InQuad);
        runflag = 1;
pAnimation->start();
    }
}

void ZAnimatedPixmapItem::StopAnimation()
{
    nStatus = 0;
}
    
void ZAnimatedPixmapItem::onAnimationFinished()
{
    runflag = 0;
    switch (completedLoops)
    {
    case 0:
    if(0 != nStatus)
    {
    comletedLoops = 1;
    pAnimation->setDuration(3000);
    pAnimation->setEasingCurve(QEasingCurve::InQuad);
    runflag = 1;
    pAnimation->start();
    }
    break;
    case 1:
    if(0 == nStatus)
    {
    pAnimation->setDuration(3000);
    pAnimation->setEasingCurve(QEasingCurve::OutQuad);
    runflag = 1;
    pAnimation->start();
    comletedLoops = 0;
    }
    else
    {
        pAnimation->setDuration(2000);
    pAnimation->setEasingCurve(QEasingCurve::Linear);
    runflag = 1;
    pAnimation->start();
    comletedLoops = 2;
    }
    break;
    case 2:
        if(0 == nStatus)
    {
    pAnimation->setDuration(3000);
    pAnimation->setEasingCurve(QEasingCurve::OutQuad);
    runflag = 1;
    pAnimation->start();
    comletedLoops = 0;
    }
    else
    {
    runflag = 1;
    pAnimation->start();
    }
    break;
    default:
    break;
    }
}

至此一个可以加速减速转动效果的动画实现了。



原文地址:https://blog.csdn.net/weixin_45694614/article/details/140522573

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!