Open
Description
QStackWidget动画(1)
使用直接提升为组件为当前组件即可。
.h
#ifndef QANIMATIONSTACKEDWIDGET_H
#define QANIMATIONSTACKEDWIDGET_H
#include <QStackedWidget>
#include <QVariant>
class QPropertyAnimation;
class QGraphicsOpacityEffect;
class QParallelAnimationGroup;
//class QVariant;
class QAnimationStackedWidget : public QStackedWidget
{
Q_OBJECT
public:
explicit QAnimationStackedWidget(QWidget *parent = Q_NULLPTR);
~QAnimationStackedWidget();
void Next();
void SwitchToIndex(int NextIndex, bool bFront = true);
void setCurrentWidget(QWidget* widget);
protected:
void paintEvent(QPaintEvent *e);
private:
QParallelAnimationGroup* m_ParlGroup;
QPropertyAnimation *m_pAnimPrty;
QGraphicsOpacityEffect* m_pAnimGraphicsEffect;
QPropertyAnimation* m_pAnimGraphics;
bool m_bAnimation;
int m_nDuration;
int m_nWidgetCount;
int m_nNextIndex;
QVariant m_nCurValue;
bool m_bMoveFront;
private:
void Init();
void paintPrevious(QPainter &paint, int currentIndex);
void paintNext(QPainter &paint, int nextIndex);
void moveAnimationStart(bool bEnter);
private slots:
void slotAnimationValueChanged(QVariant value);
void slotAnimationFinished();
};
#endif // QANIMATIONSTACKEDWIDGET_H
.cpp
#include "QAnimationStackedWidget.h"
#include <QPropertyAnimation>
#include <QPainter>
#include <QParallelAnimationGroup>
#include <QGraphicsOpacityEffect>
QAnimationStackedWidget::QAnimationStackedWidget(QWidget *parent) :
QStackedWidget(parent)
{
Init();
}
QAnimationStackedWidget::~QAnimationStackedWidget()
{
}
void QAnimationStackedWidget::Init()
{
m_bAnimation = false;
m_nDuration = 350;
m_ParlGroup = new QParallelAnimationGroup();
m_pAnimGraphicsEffect = new QGraphicsOpacityEffect(this);
m_pAnimGraphicsEffect->setOpacity(1);
this->setGraphicsEffect(m_pAnimGraphicsEffect);
m_pAnimGraphics = new QPropertyAnimation(m_pAnimGraphicsEffect, "opacity");
m_pAnimPrty = new QPropertyAnimation(this, QByteArray());
connect(m_pAnimPrty, SIGNAL(valueChanged(QVariant)), this, SLOT(slotAnimationValueChanged(QVariant)));
connect(m_pAnimPrty, SIGNAL(finished()), this, SLOT(slotAnimationFinished()));
m_pAnimPrty->setEasingCurve(QEasingCurve::InOutQuad);
m_pAnimGraphics->setEasingCurve(QEasingCurve::InOutQuad);
m_ParlGroup->addAnimation(m_pAnimPrty);
m_ParlGroup->addAnimation(m_pAnimGraphics);
}
void QAnimationStackedWidget::slotAnimationValueChanged(QVariant value)
{
m_nCurValue = value;
update();
}
void QAnimationStackedWidget::slotAnimationFinished()
{
m_bAnimation = false;
widget(currentIndex())->show();
setCurrentIndex(m_nNextIndex);
}
void QAnimationStackedWidget::paintEvent(QPaintEvent *e)
{
Q_UNUSED(e)
if(m_bAnimation)
{
QPainter paint(this);
if (m_bMoveFront)
{
//绘制当前Widget
paintPrevious(paint, currentIndex());
//绘制下一个widget
paintNext(paint, m_nNextIndex);
}
else
{
//绘制当前Widget
paintPrevious(paint, m_nNextIndex);
//绘制下一个widget
paintNext(paint, currentIndex());
}
}
}
void QAnimationStackedWidget::paintPrevious(QPainter &paint, int currentIndex)
{
//获得当前页面的Widget
QWidget *w = widget(currentIndex);
// 切换过程窗口的背景色
QString strStyle = QString("#%1{background-color: #FFFFFF}").arg(w->objectName());
w->setStyleSheet(strStyle);
QPixmap pixmap(w->size());
//将Widget的内容渲染到QPixmap对象中,即将Widget变成一张图片
w->render(&pixmap);
QRect r = w->geometry();
//绘制当前的Widget
double value = m_nCurValue.toDouble();
QRectF r1(0.0, 0.0, value, r.height());
QRectF r2(r.width() - value, 0, value, r.height());
paint.drawPixmap(r1, pixmap, r2);
}
void QAnimationStackedWidget::paintNext(QPainter &pain
6E96
t, int nextIndex)
{
QWidget *nextWidget = widget(nextIndex);
QString strStyle = QString("#%1{background-color: #FFFFFF}").arg(nextWidget->objectName());
nextWidget->setStyleSheet(strStyle);
QRect r = geometry();
//这行代码不加会有bug,第一次切换的时候,QStackedWidget并没有为child分配大小
nextWidget->resize(r.width(), r.height());
QPixmap nextPixmap(nextWidget->size());
nextWidget->render(&nextPixmap);
double value = m_nCurValue.toDouble();
QRectF r1(value, 0.0, r.width() - value, r.height());
QRectF r2(0.0, 0.0, r.width() - value, r.height());
paint.drawPixmap(r1, nextPixmap, r2);
}
void QAnimationStackedWidget::moveAnimationStart(bool bEnter)
{
if (bEnter)
{
m_pAnimPrty->setStartValue(this->width());
m_pAnimPrty->setEndValue(0);
m_pAnimGraphics->setDuration(m_nDuration);
m_pAnimGraphics->setStartValue(0);
m_pAnimGraphics->setEndValue(1);
}
else
{
m_pAnimPrty->setStartValue(0);
m_pAnimPrty->setEndValue(this->width());
m_pAnimGraphics->setDuration(m_nDuration);
m_pAnimGraphics->setStartValue(0);
m_pAnimGraphics->setEndValue(1);
}
m_pAnimPrty->setDuration(m_nDuration);
// m_pAnimPrty->start();
m_ParlGroup->start();
}
void QAnimationStackedWidget::SwitchToIndex(int index, bool bFront)
{
//如果正在动画,那么return
int curIndex = currentIndex();
m_bMoveFront = bFront;
m_bAnimation = true;
m_nWidgetCount = count();
m_nNextIndex = index;
//隐藏当前的widget
widget(curIndex)->hide();
//开始动画并设置间隔和开始、结束值
QRect g = geometry();
int width = g.width();
bFront = index >= curIndex;
moveAnimationStart(bFront);
}
void QAnimationStackedWidget::setCurrentWidget(QWidget* widget)
{
int index = indexOf(widget);
SwitchToIndex(index);
}
void QAnimationStackedWidget::Next()
{
//如果正在动画,那么return
if(m_bAnimation)
{
return;
}
m_bAnimation = true;
m_nWidgetCount = count();
int nIndex = currentIndex();
//计算下一页的索引
m_nNextIndex = (nIndex + 1) % m_nWidgetCount;
//隐藏当前的widget
widget(nIndex)->hide();
//开始动画并设置间隔和开始、结束值
QRect g = geometry();
int x = g.x();
int width = g.width();
m_pAnimPrty->setStartValue(width);
m_pAnimPrty->setEndValue(0);
m_pAnimPrty->setDuration(m_nDuration);
m_pAnimPrty->start();
Q_UNUSED(x)
}
blog link QStackWidget动画(1)