You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

326 lines
6.5 KiB

#include "animationstackedwidget.h"
#include <QPixmap>
#include <QTransform>
#include <QDebug>
AnimationStackedWidget::AnimationStackedWidget(QWidget *parent)
: QStackedWidget(parent)
{
m_isAnimating = false;
m_currentValue = 0;
m_currentIndex = 0;
m_previousIndex = 0;
m_savePreviousIndex = 0;
m_animation = new QPropertyAnimation(this, QByteArray());
m_animation->setDuration(1000);
m_animation->setEasingCurve(QEasingCurve::OutExpo);
m_animation->setStartValue(0);
m_animation->setEndValue(0);
connect(m_animation, SIGNAL(valueChanged(QVariant)), SLOT(valueChanged(QVariant)));
connect(m_animation, SIGNAL(finished()), SLOT(animationFinished()));
}
void AnimationStackedWidget::mousePressEvent(QMouseEvent *event)
{
if (m_isAnimating)
{
m_bUpdate = true;
m_canMove = false;
return;
}
m_canMove = true;
m_bUpdate = false;
m_Oncepress = true;
m_startPos = event->pos();
}
void AnimationStackedWidget::mouseMoveEvent(QMouseEvent *event)
{
if (m_isAnimating ||!m_canMove)
{
return;
}
m_bUpdate = true;
QPoint point = event->pos() - m_startPos;
if (m_Oncepress && abs(point.x()) >= 1)
{
m_Oncepress = false;
m_savePreviousIndex = m_previousIndex;
if (point.x() < 0)
{
m_bRight = false;
m_previousIndex = m_currentIndex;
if (m_currentIndex == 2)
{
m_currentIndex = 0;
}
else
{
m_currentIndex = m_currentIndex + 1;
}
}
else if(point.x() > 0)
{
m_bRight = true;
m_previousIndex = m_currentIndex;
if (m_currentIndex == 0)
{
m_currentIndex = 2;
}
else
{
m_currentIndex = m_currentIndex - 1;
}
}
}
if (m_bRight)
{
//向右移动过程中突然又向左移动
if (point.x() < 0)
{
//还原索引
m_currentValue = 0;
m_currentIndex = m_previousIndex;
m_previousIndex = m_savePreviousIndex;
//重新计算索引
m_bRight = false;
m_savePreviousIndex = m_previousIndex;
m_previousIndex = m_currentIndex;
if (m_currentIndex == 2)
{
m_currentIndex = 0;
}
else
{
m_currentIndex = m_currentIndex + 1;
}
}
else
{
m_currentValue = -m_iWidth / 2 + point.x();
}
}
if (!m_bRight)
{
//向左移动过程中突然又向右移动
if (point.x() > 0)
{
//还原索引
m_currentValue = 0;
m_currentIndex = m_previousIndex;
m_previousIndex = m_savePreviousIndex;
//重新计算索引
m_bRight = true;
m_savePreviousIndex = m_previousIndex;
m_previousIndex = m_currentIndex;
if (m_currentIndex == 0)
{
m_currentIndex = 2;
}
else
{
m_currentIndex = m_currentIndex - 1;
}
}
else
{
m_currentValue = m_iWidth / 2 + m_iWidth + point.x();
}
}
update();
currentWidget()->hide();
}
void AnimationStackedWidget::mouseReleaseEvent(QMouseEvent *event)
{
if (m_isAnimating || !m_canMove)
{
return;
}
QPoint ptDistance = event->pos() - m_startPos;
//向右滑
if (abs(ptDistance.x()) >= width() / 4 && ptDistance.x() > 0)
{
m_bRight = true;
m_currentValue = -m_iWidth / 2 + ptDistance.x();
m_animation->setStartValue(-m_iWidth / 2 + ptDistance.x());
m_animation->setEndValue(m_iWidth / 2);
int offsetx = frameRect().width();
int offsety = frameRect().height();
widget(m_currentIndex)->setGeometry(0, 0, offsetx, offsety);
currentWidget()->hide();
m_isAnimating = true;
m_animation->start();
}
//向左滑
else if (abs(ptDistance.x()) >= width() / 4 && ptDistance.x() < 0)
{
m_bRight = false;
m_currentValue = m_iWidth / 2 + m_iWidth + ptDistance.x();
m_animation->setStartValue(m_iWidth / 2 + m_iWidth + ptDistance.x());
m_animation->setEndValue(m_iWidth / 2);
int offsetx = frameRect().width();
int offsety = frameRect().height();
widget(m_currentIndex)->setGeometry(0, 0, offsetx, offsety);
currentWidget()->hide();
m_isAnimating = true;
m_animation->start();
}
//如果移动距离过小
else if (abs(ptDistance.x()) < width() / 4 && abs(ptDistance.x()) >0)
{
m_bUpdate = false;
currentWidget()->show();
m_currentValue = 0;
m_currentIndex = m_previousIndex;
m_previousIndex = m_savePreviousIndex;
}
update();
}
AnimationStackedWidget::~AnimationStackedWidget()
{
delete m_animation;
}
void AnimationStackedWidget::paintEvent(QPaintEvent * event)
{
if (m_bUpdate)
{
QPainter painter(this);
QTransform transform;
renderCurrentWidget(painter, transform);
renderPreviousWidget(painter, transform);
}
}
void AnimationStackedWidget::renderPreviousWidget(QPainter &painter, QTransform &transform)
{
QWidget *w = widget(m_previousIndex);
QRect rect = w->geometry();
QPixmap pixmap(QSize(rect.width(), rect.height()));
pixmap.fill(Qt::transparent);//用透明色填充
w->render(&pixmap);
Q_UNUSED(transform);
if (m_bRight)
{
painter.drawPixmap(width() / 2, 0, pixmap);
}
else
{
painter.drawPixmap(-width() / 2 - width(), 0, pixmap);
}
}
void AnimationStackedWidget::renderCurrentWidget(QPainter &painter, QTransform &transform)
{
QWidget *w = widget(m_currentIndex);
QRect rect = w->geometry();
QPixmap pixmap(QSize(rect.width(), rect.height()));
pixmap.fill(Qt::transparent);//用透明色填充
w->render(&pixmap);
transform.translate(m_currentValue, 0);
painter.setTransform(transform);
if (m_bRight)
{
painter.drawPixmap(-width() / 2, 0, pixmap);
}
else
{
painter.drawPixmap(-width() / 2, 0, pixmap);
}
}
void AnimationStackedWidget::start(int index)
{
if (m_isAnimating)
{
return;
}
m_bUpdate = true;
if (m_bRight)
{
m_animation->setStartValue(-m_iWidth / 2);
m_animation->setEndValue(m_iWidth / 2);
}
else
{
m_animation->setStartValue(m_iWidth / 2 + m_iWidth);
m_animation->setEndValue(m_iWidth / 2);
}
m_previousIndex = m_currentIndex;
m_currentIndex = index;
int offsetx = frameRect().width();
int offsety = frameRect().height();
widget(m_currentIndex)->setGeometry(0, 0, offsetx, offsety);
currentWidget()->hide();
m_isAnimating = true;
m_animation->start();
}
void AnimationStackedWidget::setNext(bool next)
{
m_bRight = next;
}
void AnimationStackedWidget::setLength(int length, AnimationType type)
{
m_animation->setStartValue(length / 2 + length);
m_animation->setEndValue(length / 2);
m_iWidth = length;
}
void AnimationStackedWidget::setWidgets(QList<QWidget*> lstWs)
{
m_lstWs = lstWs;
}
void AnimationStackedWidget::setPos(QList<QPoint> lstPos)
{
m_lstPos = lstPos;
m_isAnimating = false;
}
void AnimationStackedWidget::valueChanged(const QVariant &value)
{
m_currentValue = value.toFloat();
update();
}
void AnimationStackedWidget::animationFinished()
{
m_currentValue = 0;
m_bUpdate = false;
QWidget *w = widget(m_currentIndex);
setCurrentWidget(w);
emit sigGetWidgets(m_currentIndex);
update();
}