Qt實現圖片移動(2)定時器和信號槽


接昨天的圖片移動:

    在實訓的時候飛機移動有兩種,一種是玩家控制的戰機,由鍵盤來控制;一種是敵機,控制方式是定時器,Qt里面也有定時器這種東西,所以試着實現了一下。

    在昨天的基礎上加了一個cat類,閑話休絮,先把代碼貼上,慢慢解釋。

    首先是cat.h

View Code
 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文件中解釋

View Code
 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 }

    首先看構造函數

View Code
 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM