文章目錄
- 一、QPropertyAnimation 簡介
- 二、基本用法
- 三、常用屬性和方法
- 四、支持的屬性(部分常用)
- 五、多個動畫組合
- 六、使用緩和曲線
- 七、狀態機框架
一、QPropertyAnimation 簡介
#include <QPropertyAnimation>
- QPropertyAnimation 可以讓你在一段時間內平滑地修改對象的屬性值。
- 支持 QWidget 的 geometry、pos、size、windowOpacity 等屬性。
- 它基于 Qt 的 屬性系統(Q_PROPERTY),只能操作那些被 Q_PROPERTY 宏聲明過的屬性。
二、基本用法
例子:讓一個按鈕平滑移動位置
QPushButton *button = new QPushButton("Click Me", this);
button->move(0, 0);QPropertyAnimation *animation = new QPropertyAnimation(button, "pos");
animation->setDuration(1000); // 動畫持續 1000ms
animation->setStartValue(QPoint(0, 0)); // 起始位置
animation->setEndValue(QPoint(200, 200)); // 結束位置
animation->start(); // 啟動動畫
例子:讓一個按鈕平滑移動并且變大
#include <QPushButton>
#include <QPropertyAnimation>MainWindow::MainWindow(QWidget *parent): QWidget(parent)
{this->setFixedSize(800, 600);QPushButton* pBtn = new QPushButton("Animated Button", this);QPropertyAnimation *pAnimation = new QPropertyAnimation(pBtn, "geometry");pAnimation->setDuration(1000);pAnimation->setStartValue(QRect(0, 0, 120, 30));pAnimation->setEndValue(QRect(250, 250, 200, 60));pAnimation->start(QAbstractAnimation::DeleteWhenStopped);}
三、常用屬性和方法
四、支持的屬性(部分常用)
五、多個動畫組合
??在一個應用中經常會包含多個動畫,例如,要同時移動多個圖形項或者讓它們一個接一個地串行移動。使用QAnimationGroup類可以實現復雜的動畫,它的兩個子類 QSequentialAnimationGroup和QParallelAnimationGroup分別提供了串行動畫組和并行動畫組。
5.1 QParallelAnimationGroup 的使用
QParallelAnimationGroup 是 Qt 動畫框架(Qt Animation Framework)中的一個類,用于并行執行多個動畫,即多個屬性動畫同時發生。
#include <QParallelAnimationGroup>
- 它繼承自 QAnimationGroup。
- 內部可以添加多個 QPropertyAnimation(或其它動畫)。
- 所有動畫會同時啟動,彼此獨立但并行執行。
基本使用示例:
示例:按鈕同時平移、縮放、透明度變化
QPushButton *button = new QPushButton("Animate", this);
button->resize(100, 30);
button->move(50, 50);// 位置動畫
QPropertyAnimation *posAnim = new QPropertyAnimation(button, "pos");
posAnim->setDuration(1000);
posAnim->setStartValue(QPoint(50, 50));
posAnim->setEndValue(QPoint(200, 150));// 大小動畫
QPropertyAnimation *sizeAnim = new QPropertyAnimation(button, "size");
sizeAnim->setDuration(1000);
sizeAnim->setStartValue(QSize(100, 30));
sizeAnim->setEndValue(QSize(200, 60));// 透明度動畫(需設置 WA_TranslucentBackground + setWindowOpacity)
QPropertyAnimation *opacityAnim = new QPropertyAnimation(button, "windowOpacity");
opacityAnim->setDuration(1000);
opacityAnim->setStartValue(1.0);
opacityAnim->setEndValue(0.3);// 并行動畫組
QParallelAnimationGroup *group = new QParallelAnimationGroup(this);
group->addAnimation(posAnim);
group->addAnimation(sizeAnim);
group->addAnimation(opacityAnim);group->start();
常用方法和屬性:
完整示例:
#include <QPushButton>
#include <QPropertyAnimation>
#include <QParallelAnimationGroup>MainWindow::MainWindow(QWidget *parent): QWidget(parent)
{this->setFixedSize(800, 600);this->setWindowTitle("動畫");QPushButton *button = new QPushButton("Animate Me", this);button->resize(100, 30);button->move(50, 50);// 動畫 1:移動QPropertyAnimation *moveAnim = new QPropertyAnimation(button, "pos");moveAnim->setDuration(1000);moveAnim->setStartValue(QPoint(50, 50));moveAnim->setEndValue(QPoint(200, 150));// 動畫 2:縮放QPropertyAnimation *sizeAnim = new QPropertyAnimation(button, "size");sizeAnim->setDuration(1000);sizeAnim->setStartValue(QSize(100, 30));sizeAnim->setEndValue(QSize(200, 60));// 動畫 3:透明度QPropertyAnimation *opacityAnim = new QPropertyAnimation(button, "windowOpacity");opacityAnim->setDuration(1000);opacityAnim->setStartValue(1.0);opacityAnim->setEndValue(0.4);// 并行動畫組QParallelAnimationGroup *group = new QParallelAnimationGroup;group->addAnimation(moveAnim);group->addAnimation(sizeAnim);group->addAnimation(opacityAnim);QObject::connect(button, &QPushButton::clicked, [group]() {group->start(QAbstractAnimation::KeepWhenStopped);});
}
5.2 QSequentialAnimationGroup 的使用
QSequentialAnimationGroup 是 Qt 動畫框架(Qt Animation Framework)中的一個動畫組類,用于 順序地執行多個動畫 —— 即一個動畫結束后,自動執行下一個動畫,依此類推。它特別適用于需要連續步驟式動畫效果的場景,比如一個按鈕先移動 → 再放大 → 再變淡。
#include <QSequentialAnimationGroup>
- 它繼承自 QAnimationGroup。
- 內部包含多個動畫(如 QPropertyAnimation)。
- 每個動畫順序執行,一個結束后自動播放下一個。
基本使用示例:
示例:按鈕先移動 → 再變大 → 再淡出
QPushButton *button = new QPushButton("Animate", this);
button->move(50, 50);
button->resize(100, 30);// 動畫 1:移動
QPropertyAnimation *moveAnim = new QPropertyAnimation(button, "pos");
moveAnim->setDuration(1000);
moveAnim->setStartValue(QPoint(50, 50));
moveAnim->setEndValue(QPoint(200, 150));// 動畫 2:縮放
QPropertyAnimation *sizeAnim = new QPropertyAnimation(button, "size");
sizeAnim->setDuration(800);
sizeAnim->setStartValue(QSize(100, 30));
sizeAnim->setEndValue(QSize(200, 60));// 動畫 3:透明度
QPropertyAnimation *opacityAnim = new QPropertyAnimation(button, "windowOpacity");
opacityAnim->setDuration(800);
opacityAnim->setStartValue(1.0);
opacityAnim->setEndValue(0.3);// 順序動畫組
QSequentialAnimationGroup *group = new QSequentialAnimationGroup(this);
group->addAnimation(moveAnim);
group->addAnimation(sizeAnim);
group->addAnimation(opacityAnim);group->start();
常用方法:
插入等待/暫停動畫:
可以在兩個動畫之間插入暫停
group->addAnimation(moveAnim);
group->insertPause(500); // 停 500ms
group->addAnimation(sizeAnim);
完整可運行示例:
#include <QPushButton>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>MainWindow::MainWindow(QWidget *parent): QWidget(parent)
{this->setFixedSize(800, 600);this->setWindowTitle("動畫");QPushButton *button = new QPushButton("Start Animation", this);button->move(50, 50);button->resize(100, 30);// 動畫組定義QSequentialAnimationGroup *group = new QSequentialAnimationGroup;// 移動動畫QPropertyAnimation *moveAnim = new QPropertyAnimation(button, "pos");moveAnim->setDuration(1000);moveAnim->setStartValue(QPoint(50, 50));moveAnim->setEndValue(QPoint(200, 150));// 暫停動畫group->addAnimation(moveAnim);group->insertPause(1, 500);// 縮放動畫QPropertyAnimation *sizeAnim = new QPropertyAnimation(button, "size");sizeAnim->setDuration(800);sizeAnim->setStartValue(QSize(100, 30));sizeAnim->setEndValue(QSize(200, 60));group->addAnimation(sizeAnim);// 透明度動畫QPropertyAnimation *opacityAnim = new QPropertyAnimation(button, "windowOpacity");opacityAnim->setDuration(1000);opacityAnim->setStartValue(1.0);opacityAnim->setEndValue(0.3);group->addAnimation(opacityAnim);QObject::connect(button, &QPushButton::clicked, [group]() {group->start(QAbstractAnimation::KeepWhenStopped);});
}
補充說明:
- 動畫可重復播放:group->setLoopCount(n);
- 動畫結束信號:connect(group, &QSequentialAnimationGroup::finished, …)
- 可嵌套其他動畫組形成復雜流程(如先順序 → 同時多個動畫)
5.3 多個動畫的使用實例
多個組件依次動畫執行:
#include <QPushButton>
#include <QVBoxLayout>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>MainWindow::MainWindow(QWidget *parent): QWidget(parent)
{this->setFixedSize(800, 600);this->setWindowTitle("動畫");// 創建三個按鈕QPushButton *btn1 = new QPushButton("Button 1", this);QPushButton *btn2 = new QPushButton("Button 2", this);QPushButton *btn3 = new QPushButton("Button 3", this);btn1->move(20, 50);btn2->move(20, 100);btn3->move(20, 150);// 創建動畫組QSequentialAnimationGroup *group = new QSequentialAnimationGroup(this);// 按鈕 1 動畫QPropertyAnimation *anim1 = new QPropertyAnimation(btn1, "pos");anim1->setDuration(500);anim1->setEndValue(QPoint(250, 50));// 按鈕 2 動畫QPropertyAnimation *anim2 = new QPropertyAnimation(btn2, "pos");anim2->setDuration(500);anim2->setEndValue(QPoint(250, 100));// 按鈕 3 動畫QPropertyAnimation *anim3 = new QPropertyAnimation(btn3, "pos");anim3->setDuration(500);anim3->setEndValue(QPoint(250, 150));// 插入動畫到順序組group->addAnimation(anim1);group->addAnimation(anim2);group->addAnimation(anim3);// 點擊任意按鈕啟動動畫connect(btn1, &QPushButton::clicked, this, [=]{group->start();});connect(btn2, &QPushButton::clicked, this, [=]{group->start();});connect(btn3, &QPushButton::clicked, this, [=]{group->start();});
}
六、使用緩和曲線
??在 Qt 的動畫系統中,緩和曲線(Easing Curve) 用于控制動畫過程中屬性值隨時間的變化速度,也就是“動畫節奏感”。這通過 QEasingCurve 類實現,可以讓動畫效果更自然、生動,比如:
- 加速、減速(常見于 UI 移動)
- 彈跳、回彈(常見于游戲 UI)
- 彈性伸縮(擬物風格)
設置緩和曲線的方法:
每個 QPropertyAnimation 都可以通過如下方式設置緩和曲線:
QPropertyAnimation *anim = new QPropertyAnimation(widget, "pos");
anim->setDuration(1000);
anim->setStartValue(QPoint(0, 0));
anim->setEndValue(QPoint(200, 200));// 設置緩和曲線
anim->setEasingCurve(QEasingCurve::OutBounce);
常用緩和曲線類型:
示例:三種不同節奏的移動動畫
#include <QPushButton>
#include <QPropertyAnimation>MainWindow::MainWindow(QWidget *parent): QWidget(parent)
{this->setFixedSize(800, 600);this->setWindowTitle("動畫");QStringList labels = { "Linear", "OutBounce", "InOutBack" };for (int i = 0; i < 3; ++i) {QPushButton *btn = new QPushButton(labels[i], this);btn->move(20, 50 + i * 50);QPropertyAnimation *anim = new QPropertyAnimation(btn, "pos", this);anim->setDuration(1000);anim->setStartValue(QPoint(20, 50 + i * 50));anim->setEndValue(QPoint(250, 50 + i * 50));anim->setEasingCurve(QEasingCurve::OutBounce);anim->start(QAbstractAnimation::DeleteWhenStopped);}
}
此時運行程序會發現,它會使按鈕部件就像從開始位置掉落到結束位置的皮球一樣出現彈跳效果。
七、狀態機框架
什么是狀態機?
狀態機(State Machine)是一種數學模型,用來表示對象的狀態和狀態之間的切換規則。在 Qt 中,狀態機由以下核心元素組成:
- QStateMachine:狀態機管理器;
- QState / QFinalState:狀態;
- QAbstractTransition:狀態間的過渡;
- QSignalTransition:基于信號的過渡;
- QHistoryState:記住某個狀態組最后進入的子狀態(可用于“返回上次狀態”);
- QState::assignProperty():狀態進入時自動設置對象屬性(常用于動畫或 UI 狀態變化);
簡單使用示例:
場景:點擊按鈕在紅色和綠色之間切換
#include <QPushButton>
#include <QStateMachine>
#include <QState>
#include <QSignalTransition>MainWindow::MainWindow(QWidget *parent): QWidget(parent)
{this->setFixedSize(800, 600);this->setWindowTitle("動畫");QPushButton* pBtn = new QPushButton("Toggle Color", this);QStateMachine *pMachine = new QStateMachine(this);QState *redState = new QState();redState->assignProperty(pBtn, "styleSheet", "background-color: red");QState *greenState = new QState();greenState->assignProperty(pBtn, "styleSheet", "background-color: green");// 狀態切換redState->addTransition(pBtn, &QPushButton::clicked, greenState);greenState->addTransition(pBtn, &QPushButton::clicked, redState);// 添加狀態并設置初始狀態pMachine->addState(redState);pMachine->addState(greenState);pMachine->setInitialState(greenState);pMachine->start();
}
狀態機和動畫結合
結合狀態機和動畫的關鍵點:
- 利用 QState::assignProperty() 設置狀態進入時的屬性值;
- 使用 QStateMachine::addDefaultAnimation() 添加動畫,動畫會在狀態切換時自動播放;
- 動畫可作用于多種屬性(位置、大小、顏色、透明度等);
- 結合定時器和事件可以實現更復雜動畫狀態切換。
#include <QPushButton>
#include <QStateMachine>
#include <QState>
#include <QPropertyAnimation>MainWindow::MainWindow(QWidget *parent): QWidget(parent)
{this->setFixedSize(800, 600);this->setWindowTitle("動畫");QPushButton *pBtn = new QPushButton("Click me", this);pBtn->setGeometry(100, 100, 150, 50);pBtn->show();QStateMachine *pMachine = new QStateMachine(this);// 狀態1:按鈕紅色,左上角QState *state1 = new QState();state1->assignProperty(pBtn, "geometry", QRect(100, 100, 150, 50));state1->assignProperty(pBtn, "styleSheet", "background-color: red");// 狀態2:按鈕綠色,右下角QState *state2 = new QState();state2->assignProperty(pBtn, "geometry", QRect(400, 300, 150, 100));state2->assignProperty(pBtn, "styleSheet", "background-color: green");// 狀態切換state1->addTransition(pBtn, &QPushButton::clicked, state2);state2->addTransition(pBtn, &QPushButton::clicked, state1);pMachine->addState(state1);pMachine->addState(state2);pMachine->setInitialState(state1);// 添加動畫,自動在狀態切換時播放QPropertyAnimation *anim = new QPropertyAnimation(pBtn, "geometry");anim->setDuration(500);anim->setEasingCurve(QEasingCurve::InOutQuad);pMachine->addDefaultAnimation(anim);pMachine->start();
}
效果顯示: