天天看點

Qt動畫架構-(2)Qt動畫和屬性

Qt動畫和Qt類屬性

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

屬性值一般是類中的get/set方法,或者直接檢視源碼:

//QWidget的屬性(一部分)
    Q_PROPERTY(QRect geometry READ geometry WRITE setGeometry)
    Q_PROPERTY(QRect frameGeometry READ frameGeometry)
    Q_PROPERTY(QRect normalGeometry READ normalGeometry)
    Q_PROPERTY(int x READ x)
    Q_PROPERTY(int y READ y)
           

通常這個類應該用于動畫直接設定值,事實上,它的父類QVariantAnimation,有一個updateCurrentValue()的空實作,除非我們在valuechange的信号上改變它,否則它不會改變任何值。

我們選擇讓Qt屬性動起來的一個主要原因是它為我們提供了在Qt API中激活現有類的自由。值得注意的是,QWidget類(我們也可以嵌入到QGraphicsView中)有其邊界、顔色等屬性。

  • 線性插值動畫例子
Widget w;
    QLabel pix;

    pix.setPixmap(QPixmap("E:/pic/poi2.jpg"));
    pix.setParent(&w);

    w.addItem(&pix);
    w.show();

    QPropertyAnimation animation(&w, "geometry");
    animation.setDuration();

    QDesktopWidget desktop;

    animation.setStartValue(QRect(desktop.width() / ,
                            desktop.height() / ,
                            pix.width(),
                            pix.height()));
    animation.setEndValue(QRect(desktop.width() / ,
                          ,
                          pix.width(),
                          pix.height()));

    animation.start();
           

其中Widget繼承自QWidget,addItem實作如下(下文的addItem也是此函數)

void addItem(QWidget *item)
{
    if(item == nullptr)
    {
        return;
    }
    if(layout() == nullptr)
    {
        QGridLayout* l = new QGridLayout;
        l->addWidget(item);
        setLayout(l);
    }
    else
    {
        QGridLayout* l = static_cast<QGridLayout*>(layout());
        l->addWidget(item);
    }
}
           

該動畫的效果

Qt動畫架構-(2)Qt動畫和屬性

圖1 動畫示例

動畫解釋:從螢幕中心(desktop.width() / 2,desktop.height() / 2)上升到螢幕最上方(QRect(desktop.width() / 2,0)時間總長度為2s(animation.setDuration(2000))。

  • 插值動畫

上面的例子将在開始值和結束值之間進行線性插值。還可以設定位于開始和結束值之間的值。插值就會被這些點所利用。

更改部分代碼

animation.setKeyValueAt(0, QRect(desktop.width() / ,
                            desktop.height() / ,
                            pix.width(),
                            pix.height()));
    animation.setKeyValueAt(0.7, QRect(desktop.width() / ,
                          ,
                          pix.width(),
                          pix.height()));
    animation.setKeyValueAt(1, QRect(desktop.width() / ,
                            desktop.height() / ,
                            pix.width(),
                            pix.height()));

    animation.start();
           

該動畫效果

Qt動畫架構-(2)Qt動畫和屬性

圖2 插值動畫

動畫解釋:從螢幕中心上升到螢幕最上方,然後回到出發點,各比例setKeyValueAt的第一個參數時間總長度為2s。

  • Qt屬性

您還可以為未聲明為Qt屬性的QObject的值生成動畫。唯一的要求是這個值有一個setter。然後,您可以對包含該值的類進行子類化,并聲明使用此setter的屬性。請注意,每個Qt屬性都需要一個getter,是以如果沒有定義,您将需要自己提供一個getter。

class MyGraphicsRectItem : public QObject, public QGraphicsRectItem
{
    Q_OBJECT
    Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
};
           

在上面的代碼示例中,我們子類QGraphicsRectItem并定義幾何屬性。即使QGraphicsRectItem不提供幾何屬性,我們現在也可以對視窗小部件的幾何圖形進行動畫處理。(關于Qt屬性的章節将在後期更新)

  • 動畫和圖形視圖架構

當您想要動畫QGraphicsItem時,您也可以使用QPropertyAnimation。但是,QGraphicsItem不會繼承QObject。一個很好的解決方案是将您想要動畫化的圖形項子化。這個類也會繼承QObject。這樣,QPropertyAnimation可以用于QGraphicsItem。下面的例子顯示了如何完成。另一種方法是繼承QGraphicsWidget,它已經是一個QObject。

class Pixmap : public QObject, public QGraphicsPixmapItem
{
    Q_OBJECT
    Q_PROPERTY(QPointF pos READ pos WRITE setPos)
    ...
           

特别注意,QObject必須是元元對象系統要求的第一個類。

  • 簡單的曲線動畫

如前所述,QPropertyAnimation在開始和結束屬性值之間執行插值。除了為動畫添加更多的鍵值之外,您還可以使用緩動曲線。緩和曲線描述了一種控制0和1之間内插速度的函數的功能,如果要在不改變插值路徑的情況下控制動畫速度,則該方法很好用。

在第一個線性插值動畫代碼中添加一句即可

實作效果

Qt動畫架構-(2)Qt動畫和屬性

圖3 曲線動畫

通過設定QEasingCurve可以實作很多不同的效果

Qt動畫架構-(2)Qt動畫和屬性

詳細需要檢視文檔,總大概40多個 ==

繼續閱讀