@QT狀態機制--可實現動畫界面

狀態機顧名思義,應該有不一樣的狀態在切換。上面狀態機圖中,咱們提供了兩種狀態state1和state2。而狀態的區分是由狀態的屬性來描述的,好比p1,p2…等等。從一個狀態到另外一個狀態的轉化,必須由觸發條件來完成,上圖state1到state2的狀態轉換由transition1來表示,state2到state1的狀態轉換由transition2來表示。若是但願在狀態轉換過程當中有動畫來展現,那麼能夠在transition1和transition2中加入動畫效果animation1和animation2 。最後,狀態機進入須要有一個初始狀態,咱們能夠設定state1爲咱們這個狀態機的初始態。
有了狀態機的描述圖,咱們就能夠看看用Qt-4.6的 代碼,如何實現以上功能。
建立狀態機
QStateMachine *machine = new QStateMachine;
建立兩個狀態,狀態的屬性由一個QPushButton的位置大小決定。

QPushButton *button = new QPushButton(「Animated Button」);
QState *state1 = new QState(machine);
state1->assignProperty(button, 「geometry」, QRect(0, 0, 150, 30));
QState *state2 = new QState(machine);
state2->assignProperty(button, 「geometry」, QRect(250, 250, 150, 30));php

將狀態1設置爲狀態機的初始狀態
machine->setInitialState(state1);
增長觸發狀態1到狀態2的觸發條件,QPushButton按鈕被按下,動畫效果由addAnimation()完成
QSignalTransition *transition1 = state1->addTransition(button,SIGNAL(clicked()), state2);
transition1->addAnimation(new QPropertyAnimation(button, 「geometry」));
細心的讀者可能發現QPropertyAnimation的setStartValue()和setEndValue()都沒有被調用到。其實這裏動畫變化的初始態和結束態,由state1和state2決定的。另外,若是沒有設置動畫的持續時長,則默認是250毫秒。
同理,增長狀態2到狀態1的觸發條件,也是按鈕被按下
QSignalTransition *transition2 = state2->addTransition(button,SIGNAL(clicked()), state1);
transition2->addAnimation(new QPropertyAnimation(button, 「geometry」));
最後一步,將狀態機啓動便可,是否是很簡單?
machine->start();
完整代碼在下頭

 

#include <QApplication>
#include <QPushButton>
#include <QStateMachine>
#include <QState>
#include <QSignalTransition>
#include <QPropertyAnimation>
int main(int argc,char *argv[]){
QApplication app(argc,argv);
QPushButton *button = new QPushButton(「Animated Button」);
button->show();
QStateMachine *machine = new QStateMachine;
//QState *state1 = new QState(machine->rootState());
QState *state1 = new QState(machine);
state1->assignProperty(button, 「geometry」, QRect(0, 0, 150, 30));
machine->setInitialState(state1);
//QState *state2 = new QState(machine->rootState());
QState *state2 = new QState(machine);
state2->assignProperty(button, 「geometry」, QRect(250, 250, 150, 30));
QSignalTransition *transition1 = state1->addTransition(button,
SIGNAL(clicked()), state2);
transition1->addAnimation(new QPropertyAnimation(button, 「geometry」));
QSignalTransition *transition2 = state2->addTransition(button,
SIGNAL(clicked()), state1);
transition2->addAnimation(new QPropertyAnimation(button, 「geometry」));
machine->start();
app.exec();
}html

//這個代碼來自於Qt-4.6 Assistant幫助的Animation索引,原代碼的rootState()函數是沒有的,應該算是bug了吧:)git

上邊介紹了怎麼使用Qt-4.6的動畫類來實現位置的自動變化,有時候還會一些自定義屬性變化需求,好比顏色的變化,以及某些非數值直接相關的屬性,這時候能夠用自定義的變量來靈活控制。下面我實現了一個很是簡單的例子用於讓Label上的文字自動作顏色變化,不過樣子很醜 :( ,主要是演示功能windows

前文sanfanling提到QTextBrowser中選中文字的變色能夠用相似方法來操做,不過我以爲更簡便的方法是用timerEvent,呵呵(八卦一下,不知此sanfanling是否就是雲帆論壇的KDE名人三翻領?)
//這一部分代碼主要是利用繼承給QLabel增長了一個顏色屬性
#include <QApplication>
#include <QLabel>
#include <QPropertyAnimation>
app

 

class Label:public QLabel{
Q_OBJECT
Q_PROPERTY(int color READ color WRITE setColor)
public:
Label(const QString&text,QLabel *p=0):QLabel(text,p){icolor=0;};
inline const int& color() const{return icolor;};
void setColor(const int& );
private:
int icolor;
};框架

void Label::setColor(const int &rcolor) {
QPalette pal;
pal.setColor(QPalette::Foreground, rcolor);
setPalette(pal);
if(rcolor!=icolor){
icolor=rcolor;
//4 lines get 「text」
QString color_str=QString("%1").arg(icolor,2,16);
color_str+=QString("00")+color_str;
QString str=QString("");
str+=QString("http://www.cuteqt.com/blog")+QString(">") + color_str;
setText(str);
}
repaint();
}函數

//標準的QPropertyAnimation動畫接口,利用屬性color進行自動變化
int main(int argc,char *argv[]){
QApplication app(argc,argv);
Label label("hello,www.cuteqt.com/blog");oop

QPropertyAnimation *anim=new QPropertyAnimation(&label, "color");
anim->setDuration(1800);
anim->setStartValue(16);
anim->setEndValue(0xffffff);
anim->start();佈局

label.show();
return app.exec();
}動畫

#include "main.moc"

 

]]> http://www.cuteqt.com/blog/?feed=rss2&p=1146 3 http://www.cuteqt.com/blog/?p=1142 http://www.cuteqt.com/blog/?p=1142#comments Sat, 05 Dec 2009 11:20:40
+0000 臭蟲 http://www.cuteqt.com/blog/?p=1142 Qt-4.6新增了Animation Framework(動畫框架),讓咱們可以方便的寫一些生動的程序。沒必要像之前的版本同樣,全部的控件都枯燥的呆在偉大光榮的QLayout裏,也許它們能夠唱個歌,跳個舞。

 

前面寫過一篇文章Qt動畫效果的幕後英雄:QTimeLine,介紹了怎麼利用QTimeLine寫一動畫程序。今天又再重申前文裏的一句話,所謂動畫就是在一個時間段內的不一樣時間點有不一樣的狀態,只要定義好這樣狀態,實現動畫就是水到渠成的事情。固然作這件事情,最好用的就是狀態機,沒錯Qt-4.6.0提供了QStateMachine類,不過今天我要講的三字決要簡單一些。

第一決:QPropertyAnimation

QPropertyAnimation用於和QObject中的屬性properties進行通訊,好比QWidget的大小,座標等。來看代碼

QPropertyAnimation *animation = new QPropertyAnimation(myWidget, 「geometry」); 
animation->setDuration(10000); 
animation->setStartValue(QRect(0, 0, 100, 30)); 
animation->setEndValue(QRect(250, 250, 100, 30)); 
animation->start();

第一行建立的QPropertyAnimation對象關聯了myWidget這個窗體的幾何屬性。後面的幾句分別設置了這個動畫的時長,起始座標和結束座標。剩下的事情就交改QProperAnimation去作就好了。而後調用start()啓動它。沒錯,五行代碼就完成了一個完成了一個自動從一個座標點移動到另外一個座標點的窗體。下面我給出一個能夠運行的代碼,是一隻小鳥從下角移到中間的一個小動畫,固然你得本身準備這個同名的圖片:)

#include <QApplication>
#include <QLabel>
#include <QPixmap>
#include <QPropertyAnimation>

int main(int argc,char *argv[]){
QApplication app(argc,argv);
QWidget *w=new QWidget();
w->resize(300,400);

QPixmap birdimg=QPixmap(「twitter-bird.png」).scaled(40,40);

QLabel *bird_1=new QLabel(w);
bird_1->setPixmap(birdimg);

QPropertyAnimation *anim1=new QPropertyAnimation(bird_1, 「pos」);
anim1->setDuration(2000);
anim1->setStartValue(QPoint(0, 360));
anim1->setEndValue(QPoint(110, 180));
anim1->start();
bird_1->move(-40,-40);
w->show();
return app.exec();
}

上面的例子使用了label的位置屬性pos。固然你能夠在本身的類裏增長其它property的,好比讓顏色在變。

第二決:setEasingCurve

上面那個例子中小鳥的移動是線性的,未免太單調了點。QPropertyAnimation中的void setEasingCurve (const QEasingCurve & easing)函數正是用於實現不一樣的曲率變化的,QEasingCurve可用的參數列表(包括函數曲線圖)可在文檔中查到 。將上面動畫相關的代碼部分改爲

QPropertyAnimation *anim1=new QPropertyAnimation(bird_1, 「pos」);
anim1->setDuration(2000);
anim1->setStartValue(QPoint(0, 360));
anim1->setEndValue(QPoint(110, 180));
anim1->setEasingCurve(QEasingCurve::OutBounce);
anim1->start();

注意,新增的第四句。而且試試其它曲線參數,而後運行,看到的動態效果是否是不同了。若是你對列表裏已經有的曲線都不滿意,你還能夠繼承QEasingCurve,實現你須要的效果。

第三決:QAnimationGroup

前面的例子是隻有一個動畫在運行,若是想多個動畫一塊兒運行的話,那就要用到動畫組QAnimationGroup了。動畫組分爲兩種分別爲串行和並行,對應於QAnimationGroup的兩個子類QSequentialAnimationGroup和QParallelAnimationGroup。其用法很簡單

QSequentialAnimationGroup group;
//QParallelAnimationGroup group;
group.addAnimation(anim1);
group.addAnimation(anim2);
group.start();

上面的代碼,若是是串行的話,那麼動畫anim1運行以後,纔會運行anim2。若是是並行的話,兩個動畫是同時運行的。若是加了動畫組,那麼單個anim1->start()就不必再單獨調用了,由動畫組來管理。 下面是一個可運行的代碼,兩隻小鳥分別從窗體左上角和右下角移動到中間。

#include <QApplication>
#include <QWidget>
#include <QLabel>
#include <QPixmap>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>
#include <QParallelAnimationGroup>

int main(int argc,char *argv[]){
QApplication app(argc,argv);
QWidget *w=new QWidget();
w->resize(300,400);

QPixmap birdimg=QPixmap(「twitter-bird.png」).scaled(40,40);

QLabel *bird_1=new QLabel(w);
bird_1->setPixmap(birdimg);

QPropertyAnimation *anim1=new QPropertyAnimation(bird_1, 「pos」);
anim1->setDuration(2000);
anim1->setStartValue(QPoint(0, 360));
anim1->setEndValue(QPoint(110, 180));
//anim1->setEasingCurve(QEasingCurve::OutBounce);
//anim1->start();

QLabel *bird_2=new QLabel(w);
bird_2->setPixmap(birdimg);

QPropertyAnimation *anim2=new QPropertyAnimation(bird_2, 「pos」);
anim2->setDuration(2000);
anim2->setStartValue(QPoint(0, 0));
anim2->setEndValue(QPoint(150, 180));
anim2->setEasingCurve(QEasingCurve::OutBounce);

QSequentialAnimationGroup group;
//QParallelAnimationGroup group;
group.addAnimation(anim1);
group.addAnimation(anim2);
group.start();

bird_1->move(-40,-40);
bird_2->move(-40,-40);
w->show();
return app.exec();
}

其實動畫的本質就是在每必定時間間隔內顯示一幀圖像,當這個間隔較短的時候人眼就感受不出來了,以爲看到的是連續的影像。Qt爲開發動畫效果的人員提供了一個很好的時間控制類QTimeLine.

 

QTimeLine的最簡單用法是

1 QTimeLine timeline=new QTimeLine(1000);
2 timeLine->setFrameRange(0, 100);
3 connect(timeline,SIGNAL(frameChanged(int)),yourobj,SLOT(yourobjslot(int)));
4 timeline->start();

解釋:

1. 建立的時間線持續時長,參數值是毫秒數,1000就是1秒

2. 在這段時間線內,建立的輸出值範圍。也就是第三行中frameChanged信號裏傳出的參數值範圍

3. QTimeLine的默認時間間隔是40ms(也就是1秒25幀),每一個間隔會發出一個frameChanged()的信號,此處將該信號鏈接到你能控制動畫效果的對象和槽上。

4. 啓動timeline後,每一個時間間隔的frameChanged()信號才能正常發出。

固然還有一些複雜的參數設置能夠更好的控制你的效果。

setLoopCount(int count)該函數控制了動畫的重複次數。默認是1,若是設置成0則表示無限循環。

setUpdateInterval(int interval)該函數用於控制更新動畫的時間間隔。

在QTimeLine所設置的持續時長過去後,相應的會發出一個finished()的信號,你能夠在接收到這個信號之後作一些掃尾的工做。

另外還有一個別致的選項:

setCurveShape (CurveShape shape),該選項用於控制間隔輸出數值的一個變化規律。CurveShage現有的選項是

QTimeLine::EaseInCurve 0 The value starts growing slowly, then increases in speed.

QTimeLine::EaseOutCurve 1 The value starts growing steadily, then ends slowly.

QTimeLine::EaseInOutCurve 2 The value starts growing slowly, then runs steadily, then grows slowly again.

QTimeLine::LinearCurve 3 The value grows linearly (e.g., if the duration is 1000 ms, the value at time 500 ms is 0.5).

QTimeLine::SineCurve 4 The value grows sinusoidally.

QTimeLine::CosineCurve 5 The value grows cosinusoidally.

很少加解釋了,2是默認值。由於即便沒有這個選項,若是隻輸出均勻數(選項3),咱們仍是能夠本身對數據進行二次加工,生成咱們想要的任意規律的數字。

利用QTimeLine咱們很容易實現一些圖像消隱的效果,只須要你在每一個間隔結束後顯示圖像消隱過程當中不一樣階段的一個定格便可。這裏就有一個很好的例子,短短300餘行,想必用不了你多長時間便可讀通

http://qt.gitorious.org/qt-labs/graphics-dojo/trees/master/genie

咱們www.cuteqt.com/blog也奉獻一個,互相交流:)

timeline-simple.tar

]]> http://www.cuteqt.com/blog/?feed=rss2&p=509 5 http://www.cuteqt.com/blog/?p=276 http://www.cuteqt.com/blog/?p=276#comments Mon, 01 Jun 2009 02:12:51
+0000 shiroki http://www.cuteqt.com/blog/?p=276 看到qtcn上有人在問怎麼能動態的變換顯示的圖片(http://www.qtcn.org/bbs/read.php?tid=18835), 其實這是很容易實現的。 基本的是使用QTimer系列的類來控制時間, 另外從Qt4開始全部的繪製工做應該都放在窗體子類的paintEvent函數裏調用, 因此通常狀況下你須要把想定製繪圖的類派生一下, 重寫paintEvent虛函數,
把drawPixmap之類的函數放在這裏調用。 筆者的例子一方面是有點取巧, 另外一方面也爲了和問的問題一致, 沒有去派生子類, 而是用了個QLabel來顯示圖片, 各位看官在看代碼的時候要注意了。

 

下面就簡單的介紹一下程序的實現, 很是簡單, 三言兩語就清楚了。
程序的主窗體採用了QFrame, 其實隨便一個類均可以, 好比QWidget也同樣。
在主窗體中放了一個layout用來控制內部控件的佈局, Label控件和Pushbutton都放在此佈局中。 爲了顯示圖片方便, 給Label設置了一個固定大小。
構造函數就是建立佈局、子控件和定時器, 並鏈接信號和槽函數。

主類裏定義了兩個槽函數, 一個用來響應定時器並變換圖片, 另外一個用來響應用戶點擊按鈕並啓動或中止定時器。
代碼看看附件就行了, 有任何不清楚可在本站bbs留言。

例子的打包格式是tar.gz, 因爲blog上載的限制, 後綴名被篡改了, 你們下載以後本身改回去一下。 另外由於windows下的qt默認會給debug和release版本建立不一樣的目錄存放binary, 因此代碼裏用的相對路徑在windows下可能會找不到圖片, 你們拿回去改改mainwin.cpp, 或者把圖片放在程序啓動的目錄裏。 如從debug目錄運行,就要把圖片放在debug目錄中,或者若以debug\ani.exe這樣運行的話,圖片就要放在debug上級目錄。
這樣應該就能夠顯示圖片了。 Windows就是這麼麻煩!
例子程序下載: picanimation.tar.gz

]]> http://www.cuteqt.com/blog/?feed=rss2&p=276 5

相關文章
相關標籤/搜索