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

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


相关推荐
辞旧 lekkk2 小时前
【Qt】信号和槽
linux·开发语言·数据库·qt·学习·mysql·萌新
2zcode3 小时前
运动模糊图像复原的MATLAB仿真与优化
开发语言·matlab
袁雅倩19973 小时前
当吸尘器、筋膜枪都用上Type-C,供电方案该怎么选?浅谈PD取电芯片ECP5702的应用
c语言·开发语言·支持向量机·动态规划·推荐算法·最小二乘法·图搜索算法
Aaswk4 小时前
Java Lambda 表达式与流处理
java·开发语言·python
万邦科技Lafite4 小时前
京东item_get接口实战案例:实时商品价格监控全流程解析
java·开发语言·数据库·python·开放api·淘宝开放平台
liuhuizuikeai5 小时前
可视化门禁---Linux/Qt+SqLite篇
linux·运维·qt
Cyber4K5 小时前
【Python专项】进阶语法-系统资源监控与数据采集(1)
开发语言·python·php
Le_ee6 小时前
ctfweb:php/php短标签/.haccess+图片马/XXE
开发语言·前端·php
yong99906 小时前
MATLAB读取高光谱图像
开发语言·matlab
2zcode7 小时前
基于MATLAB的肝病风险评估与分期分析系统设计与实现
开发语言·matlab