一、效果图
二、工程构造思路
QStackedWidget切换界面之前,启动动画将两个界面之间的过渡界面绘制出来。待绘制完成之后,在调用setCurrentIndex来实现容器界面真正地切换。
三、代码片段
#ifndef ANIMATIONSTACKWIDGET_H
#define ANIMATIONSTACKWIDGET_H
#include <QObject>
#include <QWidget>
#include <QStackedWidget>
#include <QPropertyAnimation>
#include <QPainter>
#include <QPixmap>
#include <QLabel>
#include <QTimer>
#include <QDebug>
#include <QPushButton>
#include <QSequentialAnimationGroup>
#include <QHBoxLayout>
#include "AppWidget/animationbtn.h"
class animationstackwidget : public QStackedWidget
{
Q_OBJECT
public:
animationstackwidget(QWidget *par = nullptr);
~animationstackwidget();
void paintEvent(QPaintEvent *e);
private slots:
void valueChanged_slot(QVariant value);
void animationFinished();
private:
void paintPrev(QPainter &painter,int index);
void paintNext(QPainter &painter,int index);
void startAnimation();
private:
QVariant m_AnimationValue;
};
#endif // ANIMATIONSTACKWIDGET_H
#include "animationstackwidget.h"
animationstackwidget::animationstackwidget(QWidget *par)
:QStackedWidget(par)
{
resize(par->size());
show();
QLabel *label0 = new QLabel;
QLabel *label1 = new QLabel;
QLabel *label2 = new QLabel;
label0->setPixmap(QPixmap(":/image/1.jpg"));
label1->setPixmap(QPixmap(":/image/2.jpg"));
label2->setPixmap(QPixmap(":/image/3.jpg"));
label0->resize(this->size());
label1->resize(this->size());
label2->resize(this->size());
addWidget(label0);
addWidget(label1);
addWidget(label2);
setCurrentIndex(0);
startAnimation();
QWidget *w = new QWidget(this);
w->resize(300,5);
w->move(10,this->height()-15);
// w->setStyleSheet("background:red");
w->show();
AnimationBtn *btn0 = new AnimationBtn;
AnimationBtn *btn1 = new AnimationBtn;
AnimationBtn *btn2 = new AnimationBtn;
connect(btn0,&AnimationBtn::finished,this,[=](){
btn1->start();
});
connect(btn1,&AnimationBtn::finished,this,[=](){
btn2->start();
});
connect(btn2,&AnimationBtn::finished,this,[=](){
btn0->start();
});
QHBoxLayout *playout = new QHBoxLayout(w);
playout->addWidget(btn0);
playout->addWidget(btn1);
playout->addWidget(btn2);
playout->addStretch();
playout->setMargin(0);
playout->setSpacing(5);
btn0->start();
}
animationstackwidget::~animationstackwidget()
{
}
void animationstackwidget::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
paintPrev(painter,currentIndex());
paintNext(painter,currentIndex()+1);
}
void animationstackwidget::valueChanged_slot(QVariant value)
{
m_AnimationValue = value;
update();
}
void animationstackwidget::animationFinished()
{
widget(currentIndex())->show();
if(currentIndex() == 2)
setCurrentIndex(0);
else
setCurrentIndex(currentIndex()+1);
startAnimation();
}
void animationstackwidget::startAnimation()
{
QPropertyAnimation *m_pAnimation = new QPropertyAnimation(this, QByteArray());
connect(m_pAnimation, SIGNAL(valueChanged(QVariant)), this, SLOT(valueChanged_slot(QVariant)));
connect(m_pAnimation, SIGNAL(finished()), this, SLOT(animationFinished()));
widget(currentIndex())->hide();
m_pAnimation->setStartValue(this->geometry().width());
m_pAnimation->setEndValue(0);
m_pAnimation->setDuration(2000);
m_pAnimation->setEasingCurve(QEasingCurve::OutQuad);
m_pAnimation->start(QAbstractAnimation::DeletionPolicy::DeleteWhenStopped);
}
void animationstackwidget::paintPrev(QPainter &painter, int index)
{
QWidget* w = widget(index);
QPixmap pixmap(w->size());
w->render(&pixmap);
double value = m_AnimationValue.toDouble();
QRectF r1(0.0, 0.0, value, w->geometry().height());
QRectF r2(w->geometry().width() - value, 0, value, w->geometry().height());
painter.drawPixmap(r1, pixmap, r2);
}
void animationstackwidget::paintNext(QPainter &painter, int index)
{
QWidget* w = widget(index == 3 ? 0:index);
QPixmap pixmap(w->size());
w->render(&pixmap);
double value = m_AnimationValue.toDouble();
QRectF r1(value, 0.0, w->geometry().width()-value, w->geometry().height());
QRectF r2(0.0, 0.0, w->geometry().width()-value, w->geometry().height());
painter.drawPixmap(r1, pixmap, r2);
}
e-mail:[email protected]