QStackWidget 切换动画的实现方式,通过重写 QWidget
实现
使用重写实现的切换动画使用和展示上更稳定,推荐使用当前这个。
.h 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #ifndef MYSTACKWIDGET_H #define MYSTACKWIDGET_H
#include <QPropertyAnimation>
class MyStackWidget : public QWidget { Q_OBJECT
public: MyStackWidget(QWidget *parent); ~MyStackWidget();
int addWidget(QWidget *widget); int insertWidget(int index, QWidget *widget); void removeWidget(QWidget *widget);
int count() const;
void setWidgetsVisible();
void setCurrentWidget(QWidget *widget); void setCurrentIndex(int index); int currentIndex() const;
QWidget *currentWidget() const; QWidget *widget(int index) const; int indexOf(QWidget *widget) const;
void setDuration(int duration);
protected: void resizeEvent(QResizeEvent *event);
signals: void widgetRemoved(int); void currentChanged(int);
private slots: void onValueChanged(const QVariant &value);
private: QList<QWidget *> m_widgetLst; QPropertyAnimation *m_moveAnimation; int m_curIndex = 0; int m_offset = 0; int m_lastIndex = 0; int m_duration = 500;
void moveAnimationStart(); };
#endif
|
.cpp 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
| #include "mystackwidget.h"
#include <QDebug> #include <QPropertyAnimation>
MyStackWidget::MyStackWidget(QWidget *parent) : QWidget(parent) { m_offset = 0; m_curIndex = 0; m_lastIndex = 0; m_duration = 500; m_moveAnimation = new QPropertyAnimation(this, ""); m_moveAnimation->setDuration(m_duration); connect(m_moveAnimation, &QPropertyAnimation::valueChanged, this, &MyStackWidget::onValueChanged); }
MyStackWidget::~MyStackWidget() {
}
int MyStackWidget::count() const { return m_widgetLst.size(); }
int MyStackWidget::currentIndex() const { return m_curIndex; }
void MyStackWidget::setDuration(int duration) { m_duration = duration; }
int MyStackWidget::addWidget(QWidget * widget) { int index = indexOf(widget); if (index >= 0){ return index; } widget->setParent(this); m_widgetLst.append(widget); return count() - 1; }
int MyStackWidget::indexOf(QWidget * widget) const { return m_widgetLst.indexOf(widget); }
int MyStackWidget::insertWidget(int index, QWidget * widget) { int curindex = indexOf(widget); if (curindex >= 0) { return curindex; } widget->setParent(this); m_widgetLst.insert(index, widget); return index; }
QWidget * MyStackWidget::currentWidget() const { if (m_curIndex >= 0 && m_curIndex < count()){ return m_widgetLst.at(m_curIndex); } return nullptr; }
QWidget * MyStackWidget::widget(int index) const { if (index >= 0 && index < count()) { return m_widgetLst.at(index); } return nullptr; }
void MyStackWidget::removeWidget(QWidget * widget) { int index = indexOf(widget); if (index >= 0) { m_widgetLst.removeAll(widget); emit widgetRemoved(index); } }
void MyStackWidget::setCurrentWidget(QWidget * widget) { int index = indexOf(widget); if (index >= 0 && m_curIndex != index) { setCurrentIndex(index); } }
void MyStackWidget::setCurrentIndex(int index) { if (index >= 0 && m_curIndex != index) { m_lastIndex = m_curIndex; m_curIndex = index; moveAnimationStart(); emit currentChanged(index); } }
void MyStackWidget::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); int size = count(); for (int i = 0; i < size; i++) { m_widgetLst.at(i)->resize(this->width(), this->height()); }
if (m_moveAnimation->state() == QAbstractAnimation::Running) { moveAnimationStart(); } else { setWidgetsVisible(); } }
void MyStackWidget::onValueChanged(const QVariant &value) { m_offset = value.toInt(); m_widgetLst.at(m_curIndex)->move(m_offset, 0); if (m_curIndex > m_lastIndex) { m_widgetLst.at(m_lastIndex)->move(m_offset - this->width(), 0); } else { m_widgetLst.at(m_lastIndex)->move(this->width() + m_offset, 0); } }
void MyStackWidget::moveAnimationStart() { m_moveAnimation->stop(); setWidgetsVisible(); int startOffset = m_offset; if (m_curIndex > m_lastIndex) { if (startOffset == 0) startOffset = this->width(); else startOffset = this->width() - qAbs(startOffset); } else { if (startOffset == 0) startOffset = -this->width(); else startOffset = qAbs(startOffset) - this->width(); } m_moveAnimation->setDuration(qAbs(startOffset) * m_duration / this->width()); m_moveAnimation->setStartValue(startOffset); m_moveAnimation->setEndValue(0); m_moveAnimation->start(); }
void MyStackWidget::setWidgetsVisible() { int size = count(); for (int i = 0; i < size; i++) { if (m_lastIndex == i || m_curIndex == i) m_widgetLst.at(i)->setVisible(true); else { m_widgetLst.at(i)->setVisible(false); } } }
|