1. 程式人生 > >qt的動畫和狀態機

qt的動畫和狀態機

一 簡介

 動畫框架用於建立的GUI ,它可以為GUI快速轉換為柔和的畫面及新增原色。可以在QT提供的控制元件,QObject派生的類控制元件等元素上使用動畫效果。

狀態機 即有限狀態機,用於定義狀態之間的移動,例如,開關的行為動作可以分為ON/OFF兩種,根據其行為變為ON/OFF。如果使用狀態機,則可以簡單快捷地實現對動畫的行為組合。

動畫框架除了提供基於C++的GUI建立框架外,還提供可以再QT Quick中使用的框架。

QAbstractAnimation 所有動畫類的基類
QAnimationGroup 動畫組的抽象基類
QEasingCurve 控制動畫的Easing
QParallerAnimationGroup 並行處理多個動畫
QPauseAnimation 暫停QSequentialAnimationGroup
QSequentialAnimationGroup 序列SequentialAnimation動畫組
QVariantAnimation 動畫的抽象基類
QTimeLIne 控制動畫的時間線


二 動畫框架

本節中,我們將巨集觀瞭解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動畫框架中各個類的功能,請參考相應的類描述資訊。

三 動畫舉例

在.pro

# Made By ldp
SOURCES += \
    main.cpp \
    Widget.cpp

HEADERS += \
    Widget.h

TRANSLATIONS += zh_CN.ts //用於載入資源管理檔案翻譯

RESOURCES += \
    Resource.qrc

QT += widgets

.qm檔案是QT工程用於進行自定義中英文翻譯的原始檔,可見當年本地化、UNICODE不甚流行的時候,咱們的先烈們還想出了各種各樣的本地化招式。不多扯了,基於google的結果分析,.qm檔案是釋出出來給QT工程的translate類進行讀取的原始檔,這個檔案對於我們人是看不懂的;故而有了.ts檔案(xml格式),xml的編輯就相當方便了

TS檔案的生成:

lupdate.exe -verbose -pro xx.pro -ts xx.ts

TS檔案其格式是XML的,可以通過編譯器進行編輯或是linguist語言專家工具進行編輯翻譯。

它們的聯絡:

TS檔案———–》QM檔案(通過QT中的lrelease工具進行轉換);

轉換方法:

lrelease.exe -verbose xx.ts -qm xx.qm

或是圖形介面釋出,使用linguist,通過圖形介面去生成qm檔案

#include <QApplication>
#include <QTranslator>
#include "Widget.h"
#include "qgraphicsitem.h"

int main( int argc, char** argv )
{
    QApplication app( argc, argv );
    QTranslator trans;  //文字輸出有國際支援,翻譯
    trans.load( ":/zh_CN.qm" );//載入生成圖形管理檔案
    app.installTranslator( &trans );

    Widget w;
    w.show( );
    //設定全域性字型的大小
    QFont font = app.font();
    font.setPointSize(5);
    app.setFont(font);

    //QGraphicsItem iItem;
    //iItem.setFlag(QGraphicsItem::ItemStacksBehindParent);

    return app.exec( );
}
#include <QState>
#include <QSignalTransition>
#include "Widget.h"
#include "qdebug.h"
#include "qtimeline.h"
/*---------------------------------------------------------------------------*/
Widget::Widget( void ): QWidget( 0 )
{
    // 設定視窗的成員
    resize( 640, 360 );
    setWindowTitle( tr( "Qt_EasyAnimation2" ) );
    m_pButton = new QPushButton( tr( "Please Help" ), this );//tr translate 中文
  //  int textWidth = fontMetrics( ).width( m_pButton->text( ) );
  //  int textHeight = fontMetrics( ).height( );
    m_pButton->setGeometry(0,0,100,30);

    m_pButtonOne = new QPushButton( tr( "China" ), this );
    m_pButtonOne->setGeometry(0,40,100,30);//開始大小



    // 設定動畫和有限狀態機
    m_pMachine = new QStateMachine( this );
    QState* pState1 = new QState( m_pMachine );
    QState* pState2 = new QState( m_pMachine );
    pState1->assignProperty( m_pButton, "geometry",
                             QRect( 0, 0, 50, 15 ) );//ctl size of action  for controling
    pState2->assignProperty( m_pButton, "geometry",
                             QRect( width( )  -100,
                                    height( )  -30,
                                    100, 30 ) );// 狀態之間的變換可以實現大小也變化
    QSignalTransition* transition1 = pState1->addTransition(
                m_pButton, SIGNAL( clicked( ) ), pState2 );//
    QSignalTransition* transition2 = pState2->addTransition(
                m_pButton, SIGNAL( clicked( ) ), pState1 );
    QPropertyAnimation* pAnimation =
            new QPropertyAnimation( m_pButton, "geometry" );//set proprety
    pAnimation->setDuration( 5000 );//set time of animation
    transition1->addAnimation( pAnimation );
    transition2->addAnimation( pAnimation );//to property state
    QEasingCurve easing (QEasingCurve::InOutCubic); //實現動畫運動的方式

    for(qreal t = 0.0;t <1.0;t += 0.1)
    {
         qDebug()<<"effective progress" << t<<"is"
                <<easing.valueForProgress(t); //mapping back time
    }
    pAnimation->setEasingCurve(QEasingCurve::InCubic);

    m_pMachine->setInitialState( pState1 );// 設定初始的狀態
    m_pMachine->start();

    QTimeLine *timeline = new QTimeLine(5000); //動畫的時間控制線
    timeline->setFrameRange(0,5);//5 幀
    timeline->setDirection(QTimeLine::Forward);//增加動畫當前進行時間時,返回為0
    connect(timeline,SIGNAL(frameChanged(int)),this,SLOT(frameSlot(int)));//每一幀的變化將發出一個訊號
    timeline->start();
    connect(timeline,SIGNAL(finished()),this,SLOT(animationFinish()));
}
// 
void Widget::frameSlot(int frame)
{
         // 執行了四次
        qDebug()<<"frame is"<<frame<<endl;
        if (frame == 5)
        {
            qDebug()<<"time over later animationFinish";
        }

}
// 將動畫線完成時會發出一個finish訊號
void Widget::animationFinish()
{

    QPropertyAnimation *animation;
    animation = new QPropertyAnimation(m_pButtonOne,"geometry",this);

    animation->setDuration(3000);
    animation->setStartValue(QRect(0,40,100,30));
    animation->setEndValue(QRect(0,345,50,15));

    animation->start();



}