赞
踩
本文通过继承QStackedWidget类,实现动画功能(本文使用版本QT5.12.10)
可直接实例化QAnimationStackedWidget类,或在qtdesigner中将QStackedWidget提升为该类,或继承该类,均可直接调用动画效果
原理非常简单,其实就是通过QPropertyAnimation设置QStackedWidget中每一页的’'pos"属性,即位置属性,将每一页的显示位置移动即可实现上述效果。不过需要留意切换前后的currentIndex等细节
调用时,可设置动画持续时间(默认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
//第四个参数为遮罩层在完全出现后的停留时间
#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();
};
#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);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。