天天看點

【翻譯】Qt動畫架構

動畫架構旨在為建立動畫和流暢的 GUI 提供一種簡單的方法。通過動畫 Qt 屬性,該架構為動畫小部件和其他 QObject 提供了很大的自由。該架構還可以與圖形視圖架構一起使用。動畫架構中可用的許多概念在 Qt Quick 中也可用,它提供了一種定義動畫的聲明方式。有關動畫架構的大部分知識都可以應用于 Qt Quick。

一、動畫架構

下圖顯示了動畫架構中最重要的類。

【翻譯】Qt動畫架構

QAbstractAnimation 是所有動畫的祖先。它代表架構中所有動畫通用的基本屬性,尤其是啟動、停止和暫停動畫的能力。它還接收時間更改通知。

動畫架構進一步提供了 QPropertyAnimation 類,該類繼承 QVariantAnimation 并執行 Qt 屬性的動畫(屬性是 Qt 元對象系統的一部分)。該類使用緩動曲線對屬性執行插值。是以當想為一個值設定動畫時,可以将它聲明為一個屬性并使該類成為 QObject 的子類,這使得可以自由地為現有的小部件和其他 QObject 設定動畫。

可以通過建構 QAbstractAnimations 的樹結構來建構複雜的動畫。該樹是通過使用 QAnimationGroups 建構的,QAnimationGroups 用作其他動畫的容器。注意,組是 QAbstractAnimation 的子類,是以組本身可以包含其他組。

在幕後,動畫由全局計時器控制,該計時器向所有正在播放的動畫發送更新。

二、類清單

  • QAbstractAnimation
  • QAnimationGroup
  • QEasingCurve
  • QParallelAnimationGroup
  • QPauseAnimation
  • QPropertyAnimation
  • QSequentialAnimationGroup
  • QTimeLine
  • QVariantAnimation

三、Qt 屬性動畫

QPropertyAnimation 類可以對 Qt 屬性進行插值。

選擇為 Qt 屬性設定動畫的一個主要原因是它可以自由地為 Qt API 中的現有類設定動畫。看一個小例子:

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 秒(10000 毫秒)内将按鈕從螢幕左上角移動到位置 (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 秒内将按鈕帶到 (250, 250),然後在剩餘的 2 秒内将其移回其原始位置。運動将在這些點之間線性插值。

還可以對未聲明為 Qt 屬性的 QObject 的值進行動畫處理。唯一的要求是這個屬性有一個 setter。 注意,每個 Qt 屬性都需要一個 getter。如:

Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
           

Qt 屬性系統見:Qt屬性系統。

四、動畫和圖形視圖架構

當想要為 QGraphicsItems 設定動畫時,還可以使用 QPropertyAnimation。但是,QGraphicsItem 不繼承 QObject,需要改用 QGraphicsObject 或 QGraphicsWidget 或同時繼承 QObject 和QGraphicsItem。

class Pixmap : public QObject, public QGraphicsPixmapItem
{
    Q_OBJECT
    Q_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();
           

在這裡,動畫将遵循一條曲線,使其像球一樣反彈,就像從開始位置到結束位置一樣。QEasingCurve 有大量曲線供您選擇。這些由 QEasingCurve::Type 枚舉定義。如果需要自定義曲線,也可以自己實作一個,并用QEasingCurve注冊。

六、将動畫放在一起

應用程式通常會包含多個動畫。例如,可能希望同時移動多個圖形項目或依次移動多個圖形項。

QAnimationGroup 的子類是其他動畫的容器:

  • QParallelAnimationGroup(并行組)
  • QSequentialAnimationGroup (串行組)

QParallelAnimationGroup 示例:

QPushButton *bonnie = new QPushButton("Bonnie");
bonnie->show();
QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "geometry");

QPushButton *clyde = new QPushButton("Clyde");
clyde->show();
QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "geometry");

QParallelAnimationGroup *group = new QParallelAnimationGroup;
group->addAnimation(anim1);
group->addAnimation(anim2);

group->start();
           

一個并行組同時播放多個動畫。調用它的 start() 函數将啟動它管理的所有動畫。 

QSequentialAnimationGroup 示例:

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 按順序播放動畫。 它在上一個動畫完成後開始清單中的下一個動畫。

由于動畫組本身就是一個動畫,是以可以将其添加到另一個組中。通過這種方式,可以建構動畫的樹結構,指定動畫的播放時間。

繼續閱讀