這學期實訓的時候用MFC做過一個飛機大戰,很無聊的東西,一直想用Qt做一個,但是在學校的時候比較頹,回來看了一下。
首先需要解決的問題是圖片的移動,怎么說飛機啊子彈啊都是動着的,圖片當然要跑起來。
閑話休絮,首先用QtCreator新建一個QtGui程序,命名為PaintWidget,隨便起的名字,實驗么這不是。
會生成這三個文件,其中呢ui不用管,實驗的圖片移動需要用的是Event,不是信號槽,所以ui就不管了,放了那就是。
第一步要把圖片畫出來,參照《Qt學習之路的這段代碼》,不難把圖畫出來,就是重寫paintEvent方法,用QPainter對象來畫圖。

1 void PaintedWidget::paintEvent(QPaintEvent *event) 2 { 3 QPainter painter(this); 4 QPixmap pixmap("Cat.png"); 5 QBitmap bitmap("Cat.png"); 6 painter.drawPixmap(10, 10, 128, 128, pixmap); 7 painter.drawPixmap(140, 10, 128, 128, bitmap); 8 QPixmap pixmap2("Cat2.png"); 9 QBitmap bitmap2("Cat2.png"); 10 painter.drawPixmap(10, 140, 128, 128, pixmap2); 11 painter.drawPixmap(140, 140, 128, 128, bitmap2); 12 }
這是他的結果
問題是如何使用圖片資源:
在《C++ GUI Qt4 編程 (第二版)》這本書中有例子,直接搜這本書的源代碼,在src\chap04有發現,原來Qt引用資源是用的資源文件這個東西,是一個xml,QtCreator中很方便管理。
首先是在項目中添加文件,選擇Qt的資源文件:
因為以后可能有很多圖片,所以我在工程目錄下新建了img這么個文件夾來存放圖片。
生成的資源文件里面有個添加前綴,這個是qt中引用資源需要用的,后面再說,添加文件不用啰嗦了。
為了方便說明,先把源代碼發上來
mainwindow.h

1 #ifndef MAINWINDOW_H 2 #define MAINWINDOW_H 3 4 #include <QtGui> 5 6 namespace Ui { 7 class MainWindow; 8 } 9 10 class MainWindow : public QMainWindow 11 { 12 Q_OBJECT 13 14 public: 15 explicit MainWindow(QWidget *parent = 0); 16 ~MainWindow(); 17 protected: 18 void paintEvent (QPaintEvent *event); 19 void mouseMoveEvent(QMouseEvent *event); 20 void keyPressEvent(QKeyEvent *event); 21 22 private: 23 Ui::MainWindow *ui; 24 QPixmap *catImg; 25 QRect *catImgRect; 26 27 protected: 28 int shrinkMultiple; 29 int speed; 30 }; 31 32 #endif // MAINWINDOW_H
其中 QPixmap*catImg;就是圖片對象的指針,因為我的圖片是一直貓,所用就起了這么個名字。
QRect*catImgRect;是這個圖片的矩形信息,以為圖片移動的時候圖片的x,y坐標的值會改變,矩形信息會改變,而繪圖函數里面有個根據矩形信息和圖片指針繪制函數的這么一個函數
painter.drawPixmap(*catImgRect,*catImg);
為了方便起見,用catImgRect來存儲這些信息。
而int shrinkMultiple;這個是圖片的縮放倍數,我貓的圖片有點兒大,把他縮小了一下,當然可以沒有
這個int speed;則是圖片移動的像素數
ok,下面是mainwindow.cpp

1 #include "mainwindow.h" 2 #include "ui_mainwindow.h" 3 4 MainWindow::MainWindow(QWidget *parent) : 5 QMainWindow(parent), 6 ui(new Ui::MainWindow), 7 shrinkMultiple(2),speed(10) 8 { 9 ui->setupUi(this); 10 catImg = new QPixmap(":/img/cat.jpg"); 11 int width = catImg->width () / shrinkMultiple; 12 int height = catImg->height () / shrinkMultiple; 13 catImgRect = new QRect(10,10,width,height); 14 QRect rect = this->geometry (); 15 rect.setWidth (width*4); 16 rect.setHeight (height*4); 17 rect.setX (20); 18 rect.setY (50); 19 this->setGeometry (rect); 20 } 21 void MainWindow::paintEvent (QPaintEvent *event) 22 { 23 QPainter painter(this); 24 painter.drawPixmap(*catImgRect,*catImg); 25 } 26 void MainWindow::mouseMoveEvent(QMouseEvent *event) 27 { 28 } 29 void MainWindow::keyPressEvent(QKeyEvent *event) 30 { 31 int width = catImgRect->width (); 32 int height = catImgRect->height (); 33 switch(event->key ()) 34 { 35 case Qt::Key_Left: 36 { 37 38 catImgRect->setX (catImgRect->x ()-speed); 39 40 break; 41 } 42 case Qt::Key_Right: 43 { 44 catImgRect->setX (catImgRect->x ()+speed); 45 break; 46 } 47 case Qt::Key_Down: 48 { 49 catImgRect->setY (catImgRect->y ()+speed); 50 break; 51 } 52 case Qt::Key_Up: 53 { 54 catImgRect->setY (catImgRect->y ()-speed); 55 break; 56 } 57 } 58 catImgRect->setHeight(height); 59 catImgRect->setWidth (width); 60 this->repaint (); 61 62 } 63 MainWindow::~MainWindow() 64 { 65 delete catImg; 66 delete catImgRect; 67 delete ui; 68 }
首先看構造函數,其中
catImg=new QPixmap(":/img/cat.jpg");
這里是引用資源文件,:/img/cat.jpg,冒號后面的第一個斜杠就是剛剛加的前綴。
下面幾行是縮小貓的圖片和初始化貓矩形信息,最后一行是把程序窗口大小設這為貓圖片大小的4倍。
畫圖函數就是paintEvent這個函數,沒什么特別說的,這個函數只要是窗口一被重繪就會調用的。
關鍵的移動就是重寫
voidMainWindow::keyPressEvent(QKeyEvent*event)
這個函數,沒什么特別說明的,出了最后一行
this->repaint();
只要是鍵盤被按下,則重繪窗口,如果沒有這個函數的話,貓矩形確實變了,但是圖片的位置沒有變化,除非等到重繪的時候才會調用paintEvent函數,什么時候重繪的,當這部分窗口被遮蔽,最大化最小化,窗口移動的時候(可能還有),repaint函數的作用是立即重繪,所以圖片就能馬上移動了。
圖片移動是沒有問題了,關鍵是不是很流暢,當時用MFC的時候是用定時器來解決的這個問題,Qt中也有定時器,改天再研究,不過可能會出現問題,就是窗口閃爍的問題,這個時候應該會用到雙緩沖畫圖的技術。
貼個最終的圖片