Qt之动画框架
簡述
Qt動畫框架旨在為創建動畫和平滑的GUI提供了一種簡單的方法。通過Qt動畫屬性,該框架為部件和其它QObject對象的動畫操作提供了非常大的自由性,框架也可以被用于圖形視圖框架中,動畫框架中許多可用的概念也可以用于Qt Quick,它提供了一種聲明式的方式定義動畫。大部分關于動畫框架學到的知識都可以應用于Qt Quick。
本篇,我們闡述了Qt動畫框架的基本結構。同時,會展示最常見的技術示例,用于動畫操作QObject和圖形項。
- 簡述
- 動畫框架結構
- 動畫框架類
- Qt動畫屬性
- 動畫和圖形視圖框架
- 緩和曲線
- 動畫分組
- 動畫和狀態
- 更多參考
動畫框架結構
本節中,我們將宏觀了解Qt動畫框架的體系結構,以及如何被用于Qt動畫屬性。下圖展示了動畫框架中最重要的類。
動畫框架基礎由基類QAbstractAnimation以及它的兩個子類QVariantAnimation、QAnimationGroup組成。QAbstractAnimation是所有動畫的祖先。它包含了一些在框架中被普遍使用的基本功能,尤其是啟動、停止和暫停動畫功能,它也接收定時觸發通知。
Qt動畫框架更是提供了QPropertyAnimation類,該類繼承自QVariantAnimation,用于對Qt屬性的動畫操作(Qt屬性系統是Qt元對象系統的一部分)。QPropertyAnimation類使用緩和曲線算法對屬性進行插值演化操作。因此當你想使用動畫改變一個值時,需要聲明其為一個屬性并且使該類繼承自QObject。這給我們提供了很大的方便性,去動畫操作現有的部件和其它的QObject對象。
復雜動畫可以通過構建QAbstractAnimation樹形結構來構造。該樹主要使用QAnimationGroup,QAnimationGroup類是一個包含其它動畫類的容器類;同時QAnimationGroup類也是QAbstractAnimation類的子類,因此一個容器可以包含其它容器。
Qt動畫框架可以獨立使用,但是也被設計為Qt狀態機框架的一部分。狀態機框架提供一個特殊的狀態用來播放動畫。當狀態進入或者退出時,QState也可以改變屬性。當這個動畫狀態提供了一個QPropertyAnimatio時,這個特殊的狀態會在這些值之間進行篡改操作。后續我們將了解的更加仔細。
在幕后,動畫被一個全局定時器控制著,該定時器對所有正在運行的動畫發送更新命令。
要了解Qt動畫框架中各個類的功能,請參考相應的類描述信息。
動畫框架類
這些類提供了用于創建簡單的和復雜的動畫的框架
| QAbstractAnimation | 所有動畫類的基類 |
| QAnimationGroup | 動畫容器類的抽象基類 |
| QEasingCurve | 動畫控制的緩和曲線類 |
| QParallelAnimationGroup | 并行動畫容器 |
| QPauseAnimation | QSequentialAnimationGroup暫停 |
| QPropertyAnimation | Qt的動畫屬性 |
| QSequentialAnimationGroup | 串行動畫容器 |
| QTimeLine | 控制動畫的時間軸類 |
| QVariantAnimation | 動畫類的抽象基類 |
Qt動畫屬性
如上所述,QPropertyAnimation類能夠修改Qt屬性值,正是該類用于改變動畫屬性值。事實上,它的基類QVariantAnimation是一個抽象類,所以不能被直接使用。
選用Qt動畫屬性的一個主要原因,是因為它給我們很大的自由性去動畫操作Qt API中已經存在的類,尤其是擁有bounds、colors等屬性的QWidget類(能被嵌入到QGraphicsView中的QWidget)。
來看一個小例子:
QPushButton button("Animated Button"); button.show();QPropertyAnimation animation(&button, "geometry"); animation.setDuration(10000); animation.setStartValue(QRect(0, 0, 100, 30)); animation.setEndValue(QRect(250, 250, 100, 30));animation.start();上述代碼,在10秒的持續時間把button從屏幕的左上角移動到(250, 250)點處。
上面的例子在開始值與結束值之間做了線性插值。當然,設置的值在開始處與結束處之間的數值也是合理的,那么插值衍化就沿這些點進行。
QPushButton button("Animated Button"); button.show();QPropertyAnimation animation(&button, "geometry"); animation.setDuration(10000);animation.setKeyValueAt(0, QRect(0, 0, 100, 30)); animation.setKeyValueAt(0.8, QRect(250, 250, 100, 30)); animation.setKeyValueAt(1, QRect(0, 0, 100, 30));animation.start();這個例子中,在8秒的持續時間將button移到(250, 250),然后在剩下的2秒再移回至初始位置;這些點之間的移動都是通過線性插值的。
你也可以動畫操作沒有聲明動畫屬性的QObject對象中的值,但是唯一的條件是該值有個能進行修改的設置函數。所以可以進行子類化,在該類中包含聲明屬性的值并且有個設置函數。每個Qt屬性需要一個獲取值的訪問函數,因此如果類本身沒提供對該值的訪問函數的話,你自己就需要提供一個。
class MyGraphicsRectItem : public QObject, public QGraphicsRectItem {Q_OBJECTQ_PROPERTY(QRectF geometry READ geometry WRITE setGeometry) };如上所示的代碼例子中,我們子類化QGraphicsRectItem類,并且定義了”geometry”屬性。即使QGraphicsRectItem沒有提供”geometry”屬性,我們也可以動畫操作MyGraphicsRectItem的位置信息了。
動畫和圖形視圖框架
當你想動畫操作QGraphicsItem時,也可以使用QPropertyAnimation類。然而,QGraphicsItem并不繼承于QObject。一個好的解決辦法是子類化一個你需要的圖形項,同時這個類也繼承自QObject。通過這種方式,QPropertyAnimation類就能適用于QGraphicsItem。下面的代碼例子展示了這是如何實現的。另一種可行性是只繼承于QGraphicsWidget,因為QGraphicsWidget繼承于QObject。
class Pixmap : public QObject, public QGraphicsPixmapItem {Q_OBJECTQ_PROPERTY(QPointF pos READ pos WRITE setPos)...如上所述,我們定義了一個需要動畫操作的屬性值。
注意:出于元對象系統的要求,QObject必須是第一個繼承者。
緩和曲線
QPropertyAnimation在開始與結束之間執行插值操作。除了為動畫添加更多的鍵值外,你也可以使用緩和曲線,緩和曲線控制著在0與1之間的插值速度,如果你想在沒有改變插值路徑的情況下改變動畫速度,那么緩和曲線是很有用的。
QPushButton button("Animated Button"); button.show();QPropertyAnimation animation(&button, "geometry"); animation.setDuration(3000); animation.setStartValue(QRect(0, 0, 100, 30)); animation.setEndValue(QRect(250, 250, 100, 30));animation.setEasingCurve(QEasingCurve::OutBounce);animation.start();這里,動畫即沿著OutBounce曲線,該曲線樣式是到結束處會彈跳起來像個彈跳球。QEasingCurve類有大量供選擇的曲線,它們被定義成QEasingCurve::Type枚舉。如果你需要另外的曲線樣式,也可以自己實現一個,然后用QEasingCurve注冊它既可。
動畫分組
一個應用程序常常包含多個動畫。例如,你或許希望同時移動不止一個圖形項或者一個接一個的順序移動它們。
QAnimationGroup(QSequentialAnimationGroup和QParallelAnimationGroup)的子類是動畫容器類,因此多個動畫可以被串行或者并行執行。QAnimationGroup類就是一個例子,其不操作動畫屬性,但是它能周期性的獲得定時通知,這使得它能把定時通知應用于動畫中,從而進行控制。
下面我們來看看使用QSequentialAnimationGroup和QParallelAnimationGroup的例子:
QPushButton *bonnie = new QPushButton("Bonnie"); bonnie->show();QPushButton *clyde = new QPushButton("Clyde"); clyde->show();// 動畫一 QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "geometry");// 動畫二 QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "geometry");QParallelAnimationGroup *group = new QParallelAnimationGroup; group->addAnimation(anim1); group->addAnimation(anim2);group->start();并行容器內的動畫是同時進行的,調用它的start()函數即開始操作它所管理的所有動畫。
QPushButton button("Animated Button"); button.show();QPropertyAnimation anim1(&button, "geometry"); anim1.setDuration(3000); anim1.setStartValue(QRect(0, 0, 100, 30)); anim1.setEndValue(QRect(500, 500, 100, 30));QPropertyAnimation anim2(&button, "geometry"); anim2.setDuration(3000); anim2.setStartValue(QRect(500, 500, 100, 30)); anim2.setEndValue(QRect(1000, 500, 100, 30));QSequentialAnimationGroup group;group.addAnimation(&anim1); group.addAnimation(&anim2);group.start();毫無疑問你已經猜到了,QSequentialAnimationGroup串行的操作它所管理的動畫。
因為動畫容器類也是動畫,所以你可以將其加入到其它動畫容器里;用這種方式,就可以建造一個動畫樹結構,該結構指定了動畫彼此之間運行的關系。
動畫和狀態
當使用狀態機時,我們可以使用QSignalTransition或QEventTransition類將一個或者多個動畫與狀態之間的切換中進行關聯。這些類繼承于QAbstractTransition,QAbstractTransition類提供了便利的函數addAnimation(),該函數在狀態切換發生的情況下能觸發一個或多個被附加的動畫。
我們也可以和狀態進行屬性關聯,而不是自己設置開始和結束值,下面就是一段完整的動畫操作QPushButton位置的代碼例子:
QPushButton *button = new QPushButton("Animated Button"); button->show();QStateMachine *machine = new QStateMachine;QState *state1 = new QState(machine); state1->assignProperty(button, "geometry", QRect(0, 0, 100, 30)); machine->setInitialState(state1);QState *state2 = new QState(machine); state2->assignProperty(button, "geometry", QRect(250, 250, 100, 30));QSignalTransition *transition1 = state1->addTransition(button,SIGNAL(clicked()), state2); transition1->addAnimation(new QPropertyAnimation(button, "geometry"));QSignalTransition *transition2 = state2->addTransition(button,SIGNAL(clicked()), state1); transition2->addAnimation(new QPropertyAnimation(button, "geometry"));machine->start();有關如何使用動畫狀態機框架更全面的示例,請參見狀態示例(位于examples/animation/states目錄)。
更多參考
- The Animation Framework(助手)
- Qt之QPropertyAnimation
- Qt之QSequentialAnimationGroup
- Qt之QParallelAnimationGroup
- Qt之QPauseAnimation
- Qt之窗口動畫(下墜、抖動、透明度)
轉載于:https://www.cnblogs.com/itrena/p/5938274.html
總結
- 上一篇: mysql的partition分区
- 下一篇: Android深度探索--HAL与驱动开