這學期實訓的時候用MFC做過一個飛機大戰,很無聊的東西,一直想用Qt做一個,但是在學校的時候比較頹,回來看了一下。
首先需要解決的問題是圖片的移動,怎麼說飛機啊子彈啊都是動著的,圖片當然要跑起來。
閒話休絮,首先用QtCreator新建一個QtGui程序,命名為PaintWidget,隨便起的名字,實驗麼這不是。
會生成這三個文件,其中呢ui不用管,實驗的圖片移動需要用的是Event,不是信號槽,所以ui就不管了,放了那就是。
第一步要把圖片畫出來,參照《Qt學習之路的這段代碼》,不難把圖畫出來,就是重寫paintEvent方法,用QPainter對象來畫圖。
代碼如下:
void PaintedWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QPixmap pixmap("Cat.png");
QBitmap bitmap("Cat.png");
painter.drawPixmap(10, 10, 128, 128, pixmap);
painter.drawPixmap(140, 10, 128, 128, bitmap);
QPixmap pixmap2("Cat2.png");
QBitmap bitmap2("Cat2.png");
painter.drawPixmap(10, 140, 128, 128, pixmap2);
painter.drawPixmap(140, 140, 128, 128, bitmap2);
}
這是他的結果
問題是如何使用圖片資源:
在《C++ GUI Qt4 編程 (第二版)》這本書中有例子,直接搜這本書的源代碼,在src\chap04有發現,原來Qt引用資源是用的資源文件這個東西,是一個xml,QtCreator中很方便管理。
首先是在項目中添加文件,選擇Qt的資源文件:
因為以後可能有很多圖片,所以我在工程目錄下新建了img這麼個文件夾來存放圖片。
生成的資源文件裡面有個添加前綴,這個是qt中引用資源需要用的,後面再說,添加文件不用啰嗦了。
為了方便說明,先把源代碼發上來
mainwindow.h
代碼如下:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
void paintEvent (QPaintEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
private:
Ui::MainWindow *ui;
QPixmap *catImg;
QRect *catImgRect;
protected:
int shrinkMultiple;
int speed;
};
#endif // MAINWINDOW_H
其中 QPixmap*catImg;就是圖片對象的指針,因為我的圖片是一直貓,所用就起了這麼個名字。
QRect*catImgRect;是這個圖片的矩形信息,以為圖片移動的時候圖片的x,y坐標的值會改變,矩形信息會改變,而繪圖函數裡面有個根據矩形信息和圖片指針繪制函數的這麼一個函數
painter.drawPixmap(*catImgRect,*catImg);
為了方便起見,用catImgRect來存儲這些信息。
而int shrinkMultiple;這個是圖片的縮放倍數,我貓的圖片有點兒大,把他縮小了一下,當然可以沒有
這個int speed;則是圖片移動的像素數
ok,下面是mainwindow.cpp
代碼如下:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
shrinkMultiple(2),speed(10)
{
ui->setupUi(this);
catImg = new QPixmap(":/img/cat.jpg");
int width = catImg->width () / shrinkMultiple;
int height = catImg->height () / shrinkMultiple;
catImgRect = new QRect(10,10,width,height);
QRect rect = this->geometry ();
rect.setWidth (width*4);
rect.setHeight (height*4);
rect.setX (20);
rect.setY (50);
this->setGeometry (rect);
}
void MainWindow::paintEvent (QPaintEvent *event)
{
QPainter painter(this);
painter.drawPixmap(*catImgRect,*catImg);
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
int width = catImgRect->width ();
int height = catImgRect->height ();
switch(event->key ())
{
case Qt::Key_Left:
{
catImgRect->setX (catImgRect->x ()-speed);
break;
}
case Qt::Key_Right:
{
catImgRect->setX (catImgRect->x ()+speed);
break;
}
case Qt::Key_Down:
{
catImgRect->setY (catImgRect->y ()+speed);
break;
}
case Qt::Key_Up:
{
catImgRect->setY (catImgRect->y ()-speed);
break;
}
}
catImgRect->setHeight(height);
catImgRect->setWidth (width);
this->repaint ();
}
MainWindow::~MainWindow()
{
delete catImg;
delete catImgRect;
delete ui;
}
首先看構造函數,其中
代碼如下:
catImg=new QPixmap(":/img/cat.jpg");
這裡是引用資源文件,:/img/cat.jpg,冒號後面的第一個斜槓就是剛剛加的前綴。
下面幾行是縮小貓的圖片和初始化貓矩形信息,最後一行是把程序窗口大小設這為貓圖片大小的4倍。
畫圖函數就是paintEvent這個函數,沒什麼特別說的,這個函數只要是窗口一被重繪就會調用的。
關鍵的移動就是重寫
代碼如下:
voidMainWindow::keyPressEvent(QKeyEvent*event)
這個函數,沒什麼特別說明的,出了最後一行
代碼如下:
this->repaint();
只要是鍵盤被按下,則重繪窗口,如果沒有這個函數的話,貓矩形確實變了,但是圖片的位置沒有變化,除非等到重繪的時候才會調用paintEvent函數,什麼時候重繪的,當這部分窗口被遮蔽,最大化最小化,窗口移動的時候(可能還有),repaint函數的作用是立即重繪,所以圖片就能馬上移動了。
圖片移動是沒有問題了,關鍵是不是很流暢,當時用MFC的時候是用定時器來解決的這個問題,Qt中也有定時器,改天再研究,不過可能會出現問題,就是窗口閃爍的問題,這個時候應該會用到雙緩沖畫圖的技術。
貼個最終的圖片