Qt的簡單案例--加法計算器(詳細代碼注釋)
一、項目結構
二、項目代碼
widget.h
1 #ifndef WIDGET_H 2 #define WIDGET_H 3 //預編譯指令, 為了避免頭文件被重復包含: 如果WIDGET_H沒有被定義, 那么把WIDGET_H這個詞替換為空; 一直到下面#endif結束預編譯 4 5 #include <QWidget> 6 #include <QPushButton> 7 #include <QLineEdit> 8 #include <QLabel> 9 10 class Widget : public QWidget //子類Widget公有地繼承於父類Widget 11 { 12 Q_OBJECT //Q_OBJECT宏的作用是啟動Qt元對象系統的一些特性(如支持信號和槽等); 對於要定義信號和槽的類, 類定義的類體的開頭必須寫上Q_OBJECT宏, 並且它必須放置到類定義的私有區 13 14 public: 15 Widget(QWidget *parent = 0); //子類Widget的構造函數, 參數是一個QWidget類指針,代表它的父窗口部件(parent)。為了生成一個頂層窗口,你應該指定一個空指針作為父窗口部件(parent)。 16 ~Widget(); 17 18 //下面聲明我們即將創建的用戶界面中會用到的控件,因為這些控件不需要繼承, 也不需要在類外被訪問訪問,所以我們定義它們Widget子類的私有成員 19 private: 20 QPushButton *btn1; //記得包含相關頭文件 21 QLineEdit *edit1, *edit2; //記得包含相關頭文件 22 QLabel *label1; //記得包含相關頭文件 23 //上面的控件都會在本項目中的widget.cpp的構造函數Widget::Widget(QWidget *parent = 0)中實例化 24 //下面聲明要用到的槽函數 25 private slots: 26 void add(); 27 }; 28 29 #endif // WIDGET_H
main.cpp
1 #include "widget.h" //子類Widget的定義了我們要創建的程序中需要完成的功能,在Widget類中封裝完了這些功能。"widget.h"不是Qt的庫文件, 而是我們創建一個Qt GUI應用時, Qt為我們建立的(當然, 我們也可以自己創建這樣一個頭文件) 2 #include <QApplication> //Application 類的定義。在每一個使用Qt 圖形化應用程序中都必須使用一個QApplication 對象。QApplication 管理了各種各樣的圖形化應用程序的廣泛資源、基本設置、控制流及事件處理等 3 4 int main(int argc, char *argv[]) //應用程序的入口,幾乎在所有使用Qt的情況下,在將控制轉交給Qt庫之前, main()函數只需要執行初始化,然后Qt庫通過事件(event)向程序告知用戶的行為。所有Qt 程序中都必須有且只有一個main()函數。main()函數有兩個參數argc 和argv , argc 是命令行變量的個數,argv是命令行變量的數組。 5 { 6 QApplication a(argc, argv); //a 是這個程序的QApplication 對象。在任何Qt的窗口系統部件被使用之前, 我們創建QApplication 對象都是必須的。它在這里被創建並且處理這些命令行變量。所有被Qt 識別的命令行參數都將從argv 中被移去(並且argc也因此而減少) 7 Widget w; //創建一個Widget類對象,在該類中完成我們創建的程序的各種功能 8 w.show(); //當創建一個窗口部件的時候,默認它是不可見的,必須調用showO函數使它變為可見 9 10 return a.exec(); 11 //這一句相當於: 12 //int result = a.exec(); return result; 13 //exec()函數的作用是通過main()把控制(control)轉交給Qt,進入程序的"消息循環(message loop)"狀態,等待可能的菜單,工具條,鼠標等的輸入, 然后進行響應, 直到exit() 函數被調用來結束程序。此時exec()函數的值會返回.(Returns the value that was set to exit() (which is 0 if exit() is called via quit()) 14 //如果寫return 0;程序就直接退出了,不能達到顯示的效果。通過exec(),Qt接受並處理用戶和系統的事件並且把它們傳遞給適當的窗口部件。 15 //※ 控制: 確定數據處理系統中不同部件執行輸入、處理、存儲和輸出操作 的執行時間和順序。 16 //※ 所謂“消息循環”,實際是程序循環。即Windows 中有一個系統消息隊列,對於每一個正在執行的Windows應用程序,系統為其建立一個“消息隊列”,即應用程序隊列,用來存放該程序可能創建的各種窗口的消息。應用程序中含有一段稱作“消息循環”的代碼,用來從消息隊列中檢索這些消息並把它們分發到相應的窗口函數中。 17 }
widget.cpp
1 #include "widget.h" 2 #include <QGridLayout> 3 4 Widget::Widget(QWidget *parent) 5 : QWidget(parent) //初始化列表, 在子類中調用父類構造函數, parent的值(默認為0)傳給了QWidget()構造函數; 這是為了創建一個新的窗體, 這個窗體是一個頂層窗體(因為QWidget()構造函數的第一個形參代表父窗口, 如果對應的形參為0, 則代表生成一個父窗口) 6 { 7 btn1 = new QPushButton(this); //動態子對象btn1通過QPushButton類的構造函數創建 8 //創建子控件對象時, 需指定其parent對象. 9 //Qt的對象模型提供了一種Qt對象之間的父子關系,當很多個對象都按一定次序建立起來這種父子關系的時候,就組織成了一顆樹。 10 //當delete一個父對象的時候,Qt的對象模型機制保證了會自動的把它的所有子對象,以及孫對象,等等,全部delete,從而保證不會有內存泄漏的情況發生。 11 // 具體來說, 在每一個Qt對象中,都有一個鏈表,這個鏈表保存有它所有子對象的指針。 12 //當創建一個新的Qt對象的時候,如果把另外一個Qt對象指定為這個對象的父對象, 那么父對象就會在它的子對象鏈表中加入這個子對象的指針。另外,對於任意一個Qt對象而言,在其生命周期的任何時候,都還可以通過setParent函數 重新設置它的父對象。當一個父對象在被delete的時候,它會自動的把它所有的子對象全部delete。當一個子對象在delete的時候,會把它自己 從它的父對象的子對象鏈表中刪除。 13 //※ 唯有我們使用new創建的沒有父對象的對象才需要我們調用delete來釋放。 14 //QPushButton類的構造函數為: QPushButton::QPushButton ( QWidget * parent, const char * name = 0 ), 15 //我們看到, parent的類型為QWidget, 但this的類型為Widget, 這就說明, 父類指針形參(QWidget*)可以接受其子類指針實參(Widget*) 16 edit1 = new QLineEdit(this); 17 edit2 = new QLineEdit(this); 18 label1 = new QLabel(this); //上面都是在子類Widget的構造函數里面創建控件(即"動態對象"作"成員對象") 19 label1->setText("label1"); //setText()是對象label1的成員函數; 記得包含相關頭文件 20 btn1->setText("Get sum"); 21 QGridLayout *layout = new QGridLayout(this); //建立一個布局(layout), 這個布局是一個動態對象 22 layout->addWidget(edit1, 0, 0); 23 layout->addWidget(edit2, 0, 1); 24 layout->addWidget(btn1, 1, 0); 25 layout->addWidget(label1, 1, 1); //上面的layout對象的addWidget()成員函數用於在布局中插入控件 26 connect(btn1, SIGNAL(clicked()), this,SLOT(add()));//將btn1的點擊事件和add函數關聯 27 //connect函數語法如下: 28 //connect(sender, SIGNAL(signal()), receiver, SLOT(slot())); 29 //sender和receiver是QObject對象指針,signal 和 slot 函數一定要有形參類型(除非像這里clicked()和add()函數一樣本身就沒有形參), 但是,不可以有形參名。SIGNALE()和SLOT()宏的作用是把他們的參數轉換成字符串。 30 //如果要確定"SIGNAL(signal())"中的signal()是什么, 我們首先需要確定對象sender所屬的類型是什么, 然后去Qt文檔里面查這種類型可以有哪些signals 31 } 32 33 Widget::~Widget() 34 { 35 36 } 37 38 void Widget::add() //實現槽函數 39 { 40 QString s1 = edit1->text();//得到在edit1控件中用戶輸入的字符 41 QString s2 = edit2->text(); 42 int a = s1.toInt() + s2.toInt(); 43 label1->setText(QString::number(a)); 44 45 }
三、項目效果