qt的动画和状态机

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lvdepeng123/article/details/81410580

一 简介

 动画框架用于创建的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();



}

猜你喜欢

转载自blog.csdn.net/lvdepeng123/article/details/81410580
今日推荐