接昨天的图片移动:

    在实训的时候飞机移动有两种,一种是玩家控制的战机,由键盘来控制;一种是敌机,控制方式是定时器,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

posted on 2013-01-26 22:05  duoduo3_69  阅读(4915)  评论(1编辑  收藏  举报