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

文章目录


前言

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


一、准备

1.齿轮图片

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

2.编译环境

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

二、主要代码

1.静态图片的实现

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

cpp 复制代码
QGraphicsScene* pScene = new QGraphicsScene(this);
m_pUi->m_pPreGraphicsView->setRenderHint(QPainter::Antialiasing);
m_pUi->m_pPreGraphicsView->setScene(pScene);

将QPixmap贴图在QGraphicsPixmapItem上:

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

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

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

我们需要重写QGraphicsPixmapItem

cpp 复制代码
#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;
}
cpp 复制代码
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.动态加速度旋转图片的实现

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

cpp 复制代码
 	pAnimation->setEasingCurve(QEasingCurve::InQuad);//设置加速转动
 	pAnimation->setEasingCurve(QEasingCurve::OutQuad);//设置减速转动

如果直接冒然将加速替换匀速是不可取的,这样的后果是在一个新周期开始时动画旋转速度是0,然后到动画结束最快,然后速度突然降为0,周而复始。

为了让动画显示更具观赏性,我们需要在动画开始事件触发时的第一个周期,动画加速旋转。第一个周期结束后,动画匀速旋转,在触发了动画关闭事件后的下一个周期,动画开始减速旋转直到周期结束。

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

cpp 复制代码
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;
}
cpp 复制代码
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;
    }
}

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


相关推荐
_.Switch23 分钟前
Python 自动化运维持续优化与性能调优
运维·开发语言·python·缓存·自动化·运维开发
徐*红24 分钟前
java 线程池
java·开发语言
尚学教辅学习资料24 分钟前
基于SSM的养老院管理系统+LW示例参考
java·开发语言·java毕设·养老院
小丑西瓜66625 分钟前
qt ui设计案例--登录界面
qt·ui·c/c++·qss
1 9 J26 分钟前
Java 上机实践4(类与对象)
java·开发语言·算法
Code apprenticeship27 分钟前
Java面试题(2)
java·开发语言
J不A秃V头A29 分钟前
Python爬虫:获取国家货币编码、货币名称
开发语言·爬虫·python
SRY122404193 小时前
javaSE面试题
java·开发语言·面试
无尽的大道4 小时前
Java 泛型详解:参数化类型的强大之处
java·开发语言
ZIM学编程4 小时前
Java基础Day-Sixteen
java·开发语言·windows