一 简介
动画框架用于创建的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
#include
#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
#include
#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"
<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"<setDuration(3000);
animation->setStartValue(QRect(0,40,100,30));
animation->setEndValue(QRect(0,345,50,15));
animation->start();
}