QStackedWidget动画 含源代码,可直接调用使用

QStackedWidget切换动画 含源代码,可直接调用使用

本文通过继承QStackedWidget类,实现动画功能(本文使用版本QT5.12.10)

可直接实例化QAnimationStackedWidget类,或在qtdesigner中将QStackedWidget提升为该类,或继承该类,均可直接调用动画效果

原理简述

原理非常简单,其实就是通过QPropertyAnimation设置QStackedWidget中每一页的’'pos"属性,即位置属性,将每一页的显示位置移动即可实现上述效果。不过需要留意切换前后的currentIndex等细节

动画效果展示

  • 动画效果1 从左向右滑动
    请添加图片描述
  • 动画效果2 从左侧进入(注意观察文字位置,自行体会和上一个动画的差别)
    请添加图片描述
  • 动画效果3 向左侧退出(注意观察文字位置,自行体会和上一个动画的差别)
    请添加图片描述

调用说明

调用时,可设置动画持续时间(默认1000ms),必须设置动画类型
所有动画类型在enum AnimationMode中,亦可自行修改
L代表左,R右,U上,D下
L2R为动画效果1
FromL为动画效果2
Quit2L为动画效果3

QAnimationStackedWidget* animationStackedWidget=new QAnimationStackedWidget(this);
animationStackedWidget->setAnimationDuration(1000);
animationStackedWidget->setAnimationMode(FromL);
//调用(亦可通过信号与槽调用)
animationStackedWidget->StartStackedWidgetAnimation(0,1); //当前页面index,以及切换的页面index

组合动画效果

文章提供源代码亦提供动画效果4
请添加图片描述
本质是组合了进入与退出动画,设置了一组QSequentialAnimationGroup,文章封装好了从左向右进入,再从右向左退出的动画效果,修改动画的startValue和endValue也可实现别的方向效果。该动画主要是提供思路(其实是本人自己的项目需求)
调用时需设置动画模式为 AUTOScroll,并使用另一槽函数
(本人代码水平有限,如果直接拿来用,在设置为此动画模式后,请只使用该模式,不要在程序其它位置setAnimationMode为其它模式,否则会出问题(仅使用动画效果123的话是没有任何问题的))

animationStackedWidget->StartStackedWidgetMaskAnimation(2, 0, 1, 1000);
//第一个参数为遮罩层index,即实例中绿色3代表的index
//第二三个参数即为切换前的index及切换后的index
//第四个参数为遮罩层在完全出现后的停留时间

源代码 .h

#pragma once

#include <QStackedWidget>
#include <QPropertyAnimation>
#include <QPauseAnimation>
#include <QSequentialAnimationGroup>

enum AnimationMode{
	L2R,R2L,U2D,D2U,FromL,FromR,FromU,FromD,Quit2L, Quit2R, Quit2U, Quit2D,AUTOScroll
};

class QAnimationStackedWidget  : public QStackedWidget
{
	Q_OBJECT

public:
	QAnimationStackedWidget(QWidget *parent);
	~QAnimationStackedWidget();
	//设置动画时长
	void setAnimationDuration(int duration);
	//设置动画模式,模式在enum AnimationMode中枚举
	void setAnimationMode(int mode);
signals:
	//动画完成时发出信号
	void sStackedWidgetAnimationFinished(int indexbefore,int indexcurrent);
public slots:
	//支持除AUTOScroll外的动画
	void StartStackedWidgetAnimation(int indexbefore, int indexafter);
	//仅支持AUTOScroll动画,indexmask为遮罩层的index,septime为暂停时间
	void StartStackedWidgetMaskAnimation(int indexmask, int indexbefore, int indexafter, int septime);
private:
	QPropertyAnimation*					m_AnimationCurrent;
	QPropertyAnimation*					m_AnimationNext;
	QPauseAnimation*						m_PauseAnimation;
	QSequentialAnimationGroup*	m_AnimationGroup;
	int            m_AnimationDuration = 1000;
	double		m_AnimationCurrentValue = 0;
	int			m_AnimationMode = 0;
	int			m_lndexBeforeAnimation = 0;
	int			m_lndexAfterAnimation = 0;
	int			m_IndexMask = 0;
	bool			m_IsAnimation = false;
	bool			m_IsGroupAnimation = false;
	QPointF rectL;
	QPointF rectR;
	QPointF rectU;
	QPointF rectD;
	QPointF rect;
	void startAnimationEngine();
private slots:
	void OnAnimationFinished();
	void OnPauseAnimationFinished();
	void OnGroupAnimationFinished();
};

源代码 .cpp

#include "QAnimationStackedWidget.h"

QAnimationStackedWidget::QAnimationStackedWidget(QWidget *parent)
	: QStackedWidget(parent)
{
	m_AnimationCurrent = new QPropertyAnimation(this,"pos");
	m_AnimationNext = new QPropertyAnimation(this, "pos");
	m_PauseAnimation = new QPauseAnimation(this);
	m_AnimationGroup = new QSequentialAnimationGroup(this);
	connect(m_AnimationNext, &QPropertyAnimation::finished, this, &QAnimationStackedWidget::OnAnimationFinished);
	connect(m_AnimationCurrent, &QPropertyAnimation::finished, this, &QAnimationStackedWidget::OnAnimationFinished);
}

QAnimationStackedWidget::~QAnimationStackedWidget()
{
	if (m_AnimationCurrent) { m_AnimationCurrent->deleteLater(); m_AnimationCurrent = Q_NULLPTR; }
	if (m_AnimationNext) { m_AnimationNext->deleteLater(); m_AnimationNext = Q_NULLPTR; }
	if (m_AnimationGroup) { m_AnimationGroup->clear(); m_AnimationGroup->deleteLater(); m_AnimationGroup = Q_NULLPTR; }
	if (m_PauseAnimation) { m_PauseAnimation->deleteLater(); m_PauseAnimation = Q_NULLPTR; }
}

void QAnimationStackedWidget::OnAnimationFinished()
{
	m_IsAnimation = false;
	widget(m_lndexBeforeAnimation)->hide();
	widget(m_lndexAfterAnimation)->show();
	widget(m_lndexAfterAnimation)->raise();
	setCurrentIndex(m_lndexAfterAnimation);
	emit(sStackedWidgetAnimationFinished(m_lndexBeforeAnimation, m_lndexAfterAnimation));
}

void QAnimationStackedWidget::OnPauseAnimationFinished()
{
	widget(m_lndexBeforeAnimation)->hide();
	widget(m_lndexAfterAnimation)->show();
	widget(m_IndexMask)->show();
	widget(m_lndexAfterAnimation)->lower();
	widget(m_IndexMask)->raise();
}

void QAnimationStackedWidget::OnGroupAnimationFinished()
{
	widget(m_IndexMask)->hide();
	widget(m_lndexBeforeAnimation)->hide();
	widget(m_lndexAfterAnimation)->show();
	setCurrentIndex(m_lndexAfterAnimation);
	m_IsGroupAnimation = false;
	emit(sStackedWidgetAnimationFinished(m_lndexBeforeAnimation, m_lndexAfterAnimation));
}


void QAnimationStackedWidget::StartStackedWidgetAnimation(int indexbefore, int indexafter)
{
	if (m_IsAnimation||m_IsGroupAnimation) { return; }
	if (indexbefore >= count() || indexafter >= count() || indexbefore < 0 || indexafter < 0 || indexafter == indexbefore)
	{
		return;
	}
	m_lndexBeforeAnimation = indexbefore;
	m_lndexAfterAnimation = indexafter;
	m_AnimationCurrent->setDuration(m_AnimationDuration);
	m_AnimationNext->setDuration(m_AnimationDuration);
	m_IsAnimation = true;
	startAnimationEngine();
}

void QAnimationStackedWidget::StartStackedWidgetMaskAnimation(int indexmask,int indexbefore, int indexafter,int septime)
{
	if (m_IsAnimation || m_IsGroupAnimation) { return; }
	m_IsGroupAnimation = true;
	m_IndexMask = indexmask;
	m_lndexBeforeAnimation = indexbefore;
	m_lndexAfterAnimation = indexafter;
	m_AnimationCurrent->setTargetObject(widget(indexmask));
	m_AnimationNext->setTargetObject(widget(indexmask));
	m_AnimationCurrent->setStartValue(rectL);
	m_AnimationCurrent->setEndValue(rect);
	m_AnimationNext->setStartValue(rect);
	m_AnimationNext->setEndValue(rectL);
	m_AnimationCurrent->setDuration(m_AnimationDuration);
	m_AnimationNext->setDuration(m_AnimationDuration);
	m_PauseAnimation->setDuration(septime);
	m_AnimationGroup->addAnimation(m_AnimationCurrent);
	m_AnimationGroup->addAnimation(m_PauseAnimation);
	m_AnimationGroup->addAnimation(m_AnimationNext);
	m_AnimationGroup->start();
	widget(indexmask)->show();
	widget(indexmask)->raise();
	widget(indexbefore)->show();
}

void QAnimationStackedWidget::startAnimationEngine()
{
	m_AnimationCurrent->setTargetObject(widget(m_lndexBeforeAnimation));
	m_AnimationNext->setTargetObject(widget(m_lndexAfterAnimation));
	widget(m_lndexBeforeAnimation)->show();
	widget(m_lndexAfterAnimation)->show();
	switch (m_AnimationMode)
	{
	case R2L:
		m_AnimationCurrent->setStartValue(rect);
		m_AnimationCurrent->setEndValue(rectL);
		m_AnimationNext->setStartValue(rectR);
		m_AnimationNext->setEndValue(rect);
		m_AnimationCurrent->start();
		m_AnimationNext->start();
		break;
	case L2R:
		m_AnimationCurrent->setStartValue(rect);
		m_AnimationCurrent->setEndValue(rectR);
		m_AnimationNext->setStartValue(rectL);
		m_AnimationNext->setEndValue(rect);
		m_AnimationCurrent->start();
		m_AnimationNext->start();
		break;
	case U2D:
		m_AnimationCurrent->setStartValue(rect);
		m_AnimationCurrent->setEndValue(rectD);
		m_AnimationNext->setStartValue(rectU);
		m_AnimationNext->setEndValue(rect);
		m_AnimationCurrent->start();
		m_AnimationNext->start();
		break;
	case D2U:
		m_AnimationCurrent->setStartValue(rect);
		m_AnimationCurrent->setEndValue(rectU);
		m_AnimationNext->setStartValue(rectD);
		m_AnimationNext->setEndValue(rect);
		m_AnimationCurrent->start();
		m_AnimationNext->start();
		break;
	case FromD:
		m_AnimationNext->setStartValue(rectD);
		m_AnimationNext->setEndValue(rect);
		m_AnimationNext->start();
		widget(m_lndexAfterAnimation)->raise();
		break;
	case FromU:
		m_AnimationNext->setStartValue(rectU);
		m_AnimationNext->setEndValue(rect);
		m_AnimationNext->start();
		widget(m_lndexAfterAnimation)->raise();
		break;
	case FromL:
		m_AnimationNext->setStartValue(rectL);
		m_AnimationNext->setEndValue(rect);
		m_AnimationNext->start();
		widget(m_lndexAfterAnimation)->raise();
		break;
	case FromR:
		m_AnimationNext->setStartValue(rectR);
		m_AnimationNext->setEndValue(rect);
		m_AnimationNext->start();
		widget(m_lndexAfterAnimation)->raise();
		break;
	case Quit2D:
		m_AnimationCurrent->setStartValue(rect);
		m_AnimationCurrent->setEndValue(rectD);
		m_AnimationCurrent->start();
		m_AnimationNext->setStartValue(rect);
		m_AnimationNext->setEndValue(rect);
		m_AnimationNext->start();
		widget(m_lndexBeforeAnimation)->raise();
		break;
	case Quit2U:
		m_AnimationCurrent->setStartValue(rect);
		m_AnimationCurrent->setEndValue(rectU);
		m_AnimationCurrent->start();
		m_AnimationNext->setStartValue(rect);
		m_AnimationNext->setEndValue(rect);
		m_AnimationNext->start();
		widget(m_lndexBeforeAnimation)->raise();
		break;
	case Quit2L:
		m_AnimationCurrent->setStartValue(rect);
		m_AnimationCurrent->setEndValue(rectL);
		m_AnimationCurrent->start();
		m_AnimationNext->setStartValue(rect);
		m_AnimationNext->setEndValue(rect);
		m_AnimationNext->start();
		widget(m_lndexBeforeAnimation)->raise();
		break;
	case Quit2R:
		m_AnimationCurrent->setStartValue(rect);
		m_AnimationCurrent->setEndValue(rectR);
		m_AnimationCurrent->start();
		m_AnimationNext->setStartValue(rect);
		m_AnimationNext->setEndValue(rect);
		m_AnimationNext->start();
		widget(m_lndexBeforeAnimation)->raise();
		break;
	default:
		break;
	}

}

void QAnimationStackedWidget::setAnimationMode(int mode)
{
	m_AnimationMode = mode;
	rectL = QPointF(-width(), 0);
	rectR = QPointF(width(), 0);
	rectU = QPointF(0, -height());
	rectD = QPointF(0, height());
	rect = QPointF(0, 0);
	switch (mode)
	{
	case AUTOScroll:
		disconnect(m_AnimationNext, &QPropertyAnimation::finished, this, &QAnimationStackedWidget::OnAnimationFinished);
		disconnect(m_AnimationCurrent, &QPropertyAnimation::finished, this, &QAnimationStackedWidget::OnAnimationFinished);
		connect(m_PauseAnimation, &QPauseAnimation::finished, this, &QAnimationStackedWidget::OnPauseAnimationFinished);
		connect(m_AnimationGroup, &QSequentialAnimationGroup::finished, this, &QAnimationStackedWidget::OnGroupAnimationFinished);
		break;
	default:
		break;
	}
}

void QAnimationStackedWidget::setAnimationDuration(int duration)
{
	m_AnimationCurrent->setDuration(duration);
}

调用示例

#include "QAnimationStackedWidget.h"

QAnimationStackedWidget* animationStackedWidget; = new QAnimationStackedWidget(this);
animationStackedWidget->addWidget(....);
animationStackedWidget->setAnimationDuration(3000);
animationStackedWidget->setAnimationMode(L2R);
m_MainStackedWidget->StartStackedWidgetAnimation(0,1);
  • 9
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值