Qt
A Very Quick Overview
Eddy @ NCKU CSIE
可用方向鍵操作
Qt做遊戲懶人包
簡介
- Qt專案與QtCreator
- QObject物件系統
- Event事件系統
- Signal & Slot事件系統
- QPainter
Qt專案與QtCreator
↓
Project檔
# ← 註解開頭
# Qt 組件
QT += core gui
TEMPLATE = app
#欲編譯的檔案,每次編譯前可用下頁指令生成
SOURCES += \
main.cpp \
MyWidget.cpp \
... (and others)
HEADERS += \
MyWidget.h \
... (and others)
- 用來製作Makefile的專案資訊檔
生成Project檔--2 Ways
- qmake -project
- QtCreator
- 建立一個Qt Widget Application
- 是做遊戲入門最簡便的作法
- 取消勾選產生表單(遊戲用不到)
- 其他應該不需解釋
編譯與執行
1.使用command line
qmake-project # 更新project檔
qmake # 生成makefile
make # 編譯
./程式名稱
2.使用Qt Creator
-
尋找三角形執行按紐
→QObject物件系統
QOject物件系統
↓
- 繼承QObject的class的泛稱
- QObject才能使用signal等機制
- 有特定的記憶體管理方式
- (繼承時)有固定特殊寫法
QObject
使用QObject -記憶體
- Stack:自動配置記憶體
- 不需設定parent
- 區塊結尾自動清除
- 記憶體方面跟普通物件一樣
void some_function(){
QObject object;
} // ← 於此清除
使用QObject -記憶體
QObject *object = new QObject( parent );
- 動態配置:
- 設定parent
- (parent必須也是個QObject)
- 當parent消失時跟著消失
- 不需手動清除
- 沒設定parent
- 對要刪除的物件呼叫deleteLater
QObject *object = new QObject();
object -> deleteLater();
繼承QObject
-
待會兒會解釋為何會需要繼承
- 以QWidget為例
class MyWidget : public QWidget {
Q_OBJECT // 固定寫法,記得要補上,讓QT能在compile之前生成必要的程式碼
public:
MyWidget(QWidget *parent = 0) //讓此物件預設沒有parent,但可以明確指定
: QWidget(parent)
{
//...
}
//以下選擇性
signals: //接下來會解釋
public slots: //接下來會解釋
private:
protected:
//...
};
→Event事件實作
兩種事件系統之前...
用Qt寫程式用的是事件驅動,
也就是說,並不是一直線的執行程式,
而是「有事件時,處理該個事件」的作法。
進入事件循環→ app.exec();
初始化物件→
QApplication app;
MyWidget *widget = new Mywidget;
widget -> show();
Qt事件循環丟出事件
↓
處理事件
main↓
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyWidget *w = new MyWidget();
w -> show();
return a.exec();
}
MyWidget::MyWidget(QWidget *parent) : QWidget(parent) {
// signal&slot 機制,每隔一段時間得到timeout()事件,觸發Tick()這個自己寫的function QTimer* timer = new QTimer( this ); connect( timer, SIGNAL( timeout() ), this, SLOT( Tick() ) ); timer->start( 10 ); }
Event事件
↓
Event?
- Qt內建之訊息機制,利用繼承
- 透過Override來接收事件,並進行處理
- 用滑鼠事件示範,使用前面的MyWidget
//class宣告內加上
protected:
mousePressEvent(QMouseEvent *event); //Override
//CPP檔案實作
MyWidget::mousePressEvent(QMouseEvent *event){
cout << "Click : "
<< event -> x() << ","
<< event -> y() << endl;
}
於是就會在滑鼠點擊MyWidget時,
輸出點擊的座標。
有哪些事件可以接收?
-
QWidget
http://qt-project.org/doc/qt-4.8/qwidget.html#protected-functions
Event會放在class的protected區段,
且是virtual function
→Signal & slot
Signals & Slots
↓
特性
- 送出訊號(signal)端必須是QObject的一種
- 可使兩個不相干的物件進行溝通
-
跟event不同的是,我們可以自行產生signals
寫法
宣告
◎ 在送出事件的class:
signals:
void SomethingHappened(); //沒有實作,僅需要被呼叫
◎ 接收事件的class (直接使用public的function亦可)public slots: void SomethingToDo(); //其實跟普通的function沒有區別
實作
//Signal只代表事件發生,不做處理,故沒有內容
//Slot做處理,但不知道是什麼事件 void MyQObjectClass::SomethingToDo(){ // do something... }
connect( 來源物件,SIGNAL( SomethingHappened() ), 目標物件, SLOT( SomethingToDo() ));
// 是 QObject 的static function
觸發signal
連結
-
來源物件發生某事(Signal)時,呼叫目標物件的某Slot
emit 來源物件 -> SomethingHappened(); //emit可省略
實例
Child *child = new Child();
ScoreBoard *scoreBoard = new ScoreBoard();
QObject::connect( child , SIGNAL( beingAttack() ),
scoreBoard, SLOT( decreaseScore() ) );
//-----------
當執行child->beingAttack();時,會呼叫所有它連結到的slot
(Qt官方文件寫的是emit child->beingAttack(); , 但作用其實一模一樣)
MyWidget *widget = new MyWidget();
QTimer *timer = new QTimer();
QObject::connect( timer , SIGNAL( timeout() ),
widget, SLOT( repaint() ) );
timer -> start(10); //開始每0.01秒送出一個timeout()的signal
//每0.01秒重繪一次畫面
注意事項:
-
連結的Signal和Slot的參數要相同
- Slot和Signal的連結關係可以是多對多
- 若Slot是普通function,不需要目標物件
connect( source , SIGNAL( s() ), DoSomething )
→QPainter
QPainter
↓
可繪製物件
- QPaintDevice
- QWidget是他的子類別
藉由Override paintEvent來繪製圖形
void MyWidget::paintEvent( QPaintEvent * event ) { //當畫面需要重繪時
/* 繪出所有要出現在畫面上的東西,然後QWidget會把繪製出的圖片貼到畫面 */
QPainter painter;
painter.begin(this); //表示要在這個Widget上繪圖
// (Widget是一個QPaintDevice)
painter.fillRect( QRect(10,10,30,30) //x,y,寬,高
QColor(0,255,255,255) //yellow (RGB A)
);
}
參考資料
-
QPainter
http://qt-project.org/doc/qt-4.8/qpainter.html
-
drawPicture(畫出圖片)
- 有範例可參考
http://qt-project.org/doc/qt-4.8/qpainter.html#drawPicture
呼叫重繪
記得呼叫重繪,否則只有開啟視窗那一刻繪圖,
(或是畫面大小變動時)
平常畫面不會主動更新。
參考作法
MyWidget *widget = new MyWidget();
QTimer *timer = new QTimer();
QObject::connect( timer , SIGNAL( timeout() ),
widget, SLOT( repaint() ) );
timer -> start(10);
//每0.01秒重繪一次畫面
遊戲Loop作法參考
class Game : public QObject{ Q_OBJECT public: Game(){ QTimer *timer = new QTimer(this); QObject::connect( timer , SIGNAL( timeout() ), this , SLOT( Tick() ) ); MakeNewWindow; } void Tick() { UpdateGameObject(); window_ -> repaint(); } private: //... MyWidget *window_; }
int main(int argc,char **argv){ QApplication app(argc,argv); Game game; return app.exec(); }
End
有任何問題或錯誤歡迎在底下討論與指正
或是寄信給我
Copy of Qt
By aben20807
Copy of Qt
對於使用Qt製作2D遊戲做簡單的介紹
- 190