接昨天的圖片移動:
在實訓的時候飛機移動有兩種,一種是玩家控制的戰機,由鍵盤來控制;一種是敵機,控制方式是定時器,Qt里面也有定時器這種東西,所以試着實現了一下。
在昨天的基礎上加了一個cat類,閑話休絮,先把代碼貼上,慢慢解釋。
首先是cat.h

1 #ifndef CAT_H 2 #define CAT_H 3 4 #include <QtGui> 5 6 class Cat : public QWidget 7 { 8 Q_OBJECT 9 public: 10 explicit Cat(QWidget *parent = 0); 11 ~Cat(); 12 protected: 13 void paintEvent (QPaintEvent *event); 14 void mousePressEvent(QMouseEvent *event); 15 16 private: 17 QPixmap *catImg; 18 QRect *catImgRect; 19 QTimer *catTimer; 20 protected: 21 int shrinkMultiple; 22 int speed; 23 bool stop; 24 signals: 25 void clicked(); 26 public slots: 27 void mousePressEventSlot(); 28 29 void run(); 30 }; 31 32 #endif // CAT_H
1 private: 2 QPixmap *catImg; 3 QRect *catImgRect; 4 5 protected: 6 int shrinkMultiple; 7 int speed; 8
這幾個和上一節完全一樣,不解釋了,加了幾個變量,信號槽:
1、QTimer *catTimer; 就是傳說中的定時器,用信號槽的方式來使用
connect(catTimer,SIGNAL(timeout()),this,SLOT(run()));
catTimer->start(20);
解釋:timeout是Qt自己的信號,比如這個例子,start是說讓catTimer定時器開始工作,時間是20毫秒,當20毫秒過后,Qt會發出timeout信號,將run這個槽的函數加入到某個隊列里面(隊列具體的名字和作用我忘了),來依次處理。
2、bool stop; 因為我想要讓運動的圖片暫停,所以加了這么一個變量
3、兩個槽
1 public slots: 2 void mousePressEventSlot(); 3 4 void run();
具體用法在cpp文件中解釋

1 #include "cat.h" 2 3 Cat::Cat(QWidget *parent) : 4 QWidget(parent),shrinkMultiple(2), 5 speed(10),stop(true) 6 { 7 catImg = new QPixmap(":/img/little_cat.jpg"); 8 int width = catImg->width ()/shrinkMultiple; 9 int height = catImg->height ()/shrinkMultiple; 10 catImgRect = new QRect(10,10,width,height); 11 12 catTimer = new QTimer(this); 13 14 connect( this, SIGNAL( clicked() ), this, SLOT( mousePressEventSlot() ) ); 15 connect( catTimer,SIGNAL(timeout()),this,SLOT(run())); 16 17 } 18 void Cat::paintEvent (QPaintEvent *event) 19 { 20 QPainter painter(this); 21 22 painter.drawPixmap(*catImgRect,*catImg); 23 } 24 void Cat::mousePressEvent(QMouseEvent *event) 25 { 26 if (catImgRect->contains (event->x(),event->y())) 27 { 28 stop = !stop; 29 emit clicked(); 30 } 31 } 32 void Cat::run() 33 { 34 int width = catImgRect->width (); 35 catImgRect->setX (catImgRect->x ()+10); 36 catImgRect->setWidth (width); 37 repaint (); 38 } 39 void Cat::mousePressEventSlot () 40 { 41 if(!stop) 42 { 43 catTimer->start (20); 44 } 45 else 46 { 47 catTimer->stop (); 48 } 49 50 } 51 Cat::~Cat() 52 { 53 delete catImg; 54 delete catImgRect; 55 delete catTimer; 56 }
首先看構造函數

1 Cat::Cat(QWidget *parent) : 2 QWidget(parent),shrinkMultiple(2), 3 speed(10),stop(true) 4 { 5 catImg = new QPixmap(":/img/little_cat.jpg"); 6 int width = catImg->width ()/shrinkMultiple; 7 int height = catImg->height ()/shrinkMultiple; 8 catImgRect = new QRect(10,10,width,height); 9 10 catTimer = new QTimer(this); 11 12 connect( this, SIGNAL( clicked() ), this, SLOT( mousePressEventSlot() ) ); 13 connect( catTimer,SIGNAL(timeout()),this,SLOT(run())); 14 15 }
到new定時器之前的東西就不講了,和昨天畫貓的地方一樣。
1 catTimer = new QTimer(this); 2 3 connect( this, SIGNAL( clicked() ), this, SLOT( mousePressEventSlot() ) ); 4 connect( catTimer,SIGNAL(timeout()),this,SLOT(run()));
這里,鏈接了兩個信號槽,我打算的是點擊圖片,貓開始跑,再點擊,貓停止,這么着跑跑停停的。
很自然,鏈接clicked和mousePressEventSlot,點擊信號對應鼠標按下事件的槽嘛;
為什么要用catTimer鏈接run呢,這是為了讓圖片能夠一直運動,圖片是根據catImgRect這個矩形信息來繪制的,如果讓圖片運動,很自然的就像讓圖片沒秒往某幾個方向移動幾個像素,如果沒用定時器的話,咱們可能用一個while循環來實現,有定時器就不用這么麻煩了。
首先看mousePressEvent,相較更低的Event函數,因為有事件的時候肯定會先找事件的函數來處理
1 void Cat::mousePressEvent(QMouseEvent *event) 2 { 3 if (catImgRect->contains (event->x(),event->y())) 4 { 5 stop = !stop; 6 emit clicked(); 7 } 8 }
當鼠標按下的時候,如果按鍵的坐標點在catImgRect這個矩形中,說明鼠標點到我們的貓仔圖片了,那么原來的運動狀態就轉換為相反的值,原來動變成停,停變成動,然后才發出圖片被點中了的clicked信號。
當信號發出時,由於下面這行的存在,所以會出發觸發mousePressEventSlot這個函數
1 connect( this, SIGNAL( clicked() ), this, SLOT( mousePressEventSlot() ) );
mousePressEventSlot這個函數和run函數合在一起是為了控制圖片運動或者停止的,run函數是說每次向右移動10個像素,並且重繪,而因為下面這個信號槽的存在,run和catTmer定時器鏈接在了一起,當定時器啟動的時候,處理run函數,停止的話就不動了唄。因此,我在mousePressEventSlot這個槽里面處理了定時器的啟動與停止。
1 connect( catTimer,SIGNAL(timeout()),this,SLOT(run()));
下面是run和mousePressEventSlot
1 void Cat::run() 2 { 3 int width = catImgRect->width (); 4 catImgRect->setX (catImgRect->x ()+10); 5 catImgRect->setWidth (width); 6 repaint (); 7 } 8 void Cat::mousePressEventSlot () 9 { 10 if(!stop) 11 { 12 catTimer->start (20); 13 } 14 else 15 { 16 catTimer->stop (); 17 } 18 19 }
定時器為什么選擇20毫秒的,開始的時候我用的是50,結果又停滯感,就是西卡一卡的,定時器的時間間隔越兄啊,圖片運動越流暢,越沒有停頓感。道理很簡單,你想啊,如果一個圖片每1秒移動然后重新畫一下圖肯定比每10秒移動重畫圖片要流暢,沒有一卡一卡的感覺。
最后上截圖,運動的截圖,比較蛋疼,就隨便截截圖吧,實際上是點擊,貓運動,在點擊,貓停止,如此反復。
ps:因為是在昨天的工程里做的,原來的鍵盤貓還有。
開始的時候
點擊運動后
pps:為什么要做這兩篇Qt移動圖片呢?原因是我們下學期要學設計模式這個東西,老師很英明的選擇了《head first設計模式》這本書,確實是好書,之前我讀過,里面使用java,依然是命令行的模式,我突然想能不能用圖形的給實現一下,看了里面第一張的策略模式,里面是鴨子的飛行,剛好可以放在這當貓的run,我就想利用圖片的上下左右移動當做duck不同的飛行動作,恩,就是這樣。
ppps:玩Qt什么的,只想說一句話,一切為了python