1.3 MyFirstWidget代碼講解及實用編程技巧分享

前兩節我們已經安裝Qt環境,並且熟悉了QtCreator開發界面。本節接著前面的部分,分析講解MyFirstWidget代碼,並且提供一個非常有用的編程技巧,而且小豆君會在後續的分享中都會 適當的加入一些編程技巧,編程思想等,以方便大家的代碼更精簡有效。如果有不對的地方,也歡迎大牛們指出。

1.3.1 main.cpp

<code>2 #include "myfirstwidget.h"
3
4 int main(int argc, char *argv[])
5 {
6 QApplication a(argc, argv);
7
8 MyFirstWidget w;
9 w.show();

10 return a.exec();
11 }/<code>

為了敘述方便,現約定:在以後的代碼分析中,方括號中的數字代表行號,例如【1-3】表示第1行到第3行的代碼。

【1】包含QApplication類。

【2】包含myfirstwidget.h頭文件,這是我們創建窗口類時,Qt自動為我們生成的頭文件,且文件名都為小寫。

【4-11】main函數。

【6】創建一個QApplication實例。

如果所創建的是一個窗口應用程序,那麼必須要有且只有一個這樣的實例,在創建QApplication實例後,會自動將指針賦值給Qt的全局變量qApp,如果想在其它地方使用QApplication實例,則可以直接調用qApp。因為QApplication實例會進行大量的初始化工作,所以要在使用任何對象之前就創建QApplication實例,因此,main函數開頭便創建了QApplication實例。

如果創建的是一個非窗口的應用程序,那麼可以調用QCoreApplication來創建實例。

QApplication主要做以下事情(只需瞭解即可):

  • 使用用戶的桌面設置,初始化應用程序,例如窗口的調色板,字體等。
  • 執行事件處理。
  • 也可根據命令行參數,設置自己的內部狀態。
  • 制定窗口樣式,顏色調配,文字國際化。
  • 設置剪切板,管理鼠標事件。

【8-9】創建MyFirstWidget實例,並顯示。

【10】進入Qt的主循環事件。當調用exit()函數時,才會退出循環,退出main函數。當程序在準備退出主循環時,會發出aboutToQuit()信號,如果有某些在退出程序前要處理的事情,可鏈接此信號進行處理。除了主循環外,Qt還有本地循環,可以理解為子循環,這個會在後面的講解中講述。

1.3.2 myfirstwidget.h

<code>2 #define MYFIRSTWIDGET_H

3 #include <qwidget>

4 namespace Ui {
5 class MyFirstWidget;
6 }


7 class MyFirstWidget : public QWidget
8 {
9 Q_OBJECT

10 public:
11 explicit MyFirstWidget(QWidget *parent = 0);
12 ~MyFirstWidget();

13 private:
14 Ui::MyFirstWidget *ui;
15 };

16 #endif // MYFIRSTWIDGET_H
/<qwidget>/<code>

【7】MyFirstWidget公有繼承QWidget,這樣我們就可以調用QWidget提供的方法。QWidget是所有Qt窗口控件的基類,一般情況自定義窗口控件都應該繼承QWidget或其子類,關於QWidget的內容小豆君會以後進行介紹。

【9】Q_OBJECT宏,必須在類的私有聲明中聲明這個宏,這樣就可以使用Qt的信號槽機制,元對象系統,對象樹等Qt特有的功能,否則無法使用。所以這裡推薦在創建類時,最好加上此聲明,這樣的代碼會得到很多Qt提供的便利接口。

【11】構造函數,其中parent參數,可指定父窗口,關於父子窗口的概念會在下節介紹。

【14】ui界面對象指針,凡是需要ui界面中的控件對象指針,都可以通過這個指針來進行調用訪問。

1.3.3 myfirstwidget.cpp

<code>1 #include "myfirstwidget.h" 

2 #include "ui_myfirstwidget.h"

3 MyFirstWidget::MyFirstWidget(QWidget *parent) :
4 QWidget(parent),
5 ui(new Ui::MyFirstWidget)
6 {
7 ui->setupUi(this);
8 }

9 MyFirstWidget::~MyFirstWidget()
10 {
11 delete ui;
12 }
/<code>

【4】如果有參數parent不為空,則MyFirstWidget會成為該指針所指窗口的子窗口。

【5】創建Ui::MyFirstWidget界面對象,並將指針賦值給ui,創建的對象會在析構函數中釋放。

【7】設置ui界面。

1.3.4 myfirstwidget.ui

雙擊myfirstwidget.ui進入Qt設計師界面,如下圖:

1.3 MyFirstWidget代碼講解及實用編程技巧分享

打開的設計師界面,初始為一個空的窗口,現在可以嘗試從左側控件列表樹中拖拽控件到中間的設計窗口,例如拖一個QLabel,QComboBox,QPushButton,QLineEdit,QCheckBox,可以在filter過濾器中輸入關鍵字,這幫助你快速找到需要的控件。

鼠標點擊剛剛拖入的QLineEdit控件,在右下角的屬性編輯器中的filter過濾器中輸入text,查找屬性text,修改text的值為“Hello Qt”,回車。你會發現在設計窗口中QLineEdit控件顯示Hello Qt字樣。


1.3 MyFirstWidget代碼講解及實用編程技巧分享

好的,那我們再查找屬性objectName,此時對應顯示值為lineEdit,請記住這個值

1.3 MyFirstWidget代碼講解及實用編程技巧分享

我們再打開myfirstwidget.cpp文件,在構造函數中輸入“ui->“此時會彈出一個ui所擁有的對象列表,選擇lineEdit對象,這個lineEdit恰好就是在剛剛的屬性面板中設置的值,Qt會將對象的名稱用作對象的變量名,還可以通過調用findChild函數模版查找對應屬性名的對象。調用setText方法如下:

<code>2 #include "myfirstwidget.h" 

3
4 int main(int argc, char *argv[])
5 {
6 QApplication a(argc, argv);
7
8 MyFirstWidget w;
9 w.show();

10 return a.exec();
11 }/<code>

Ctrl+R,運行程序,最後可看到lineEdit顯示了This is MyFirstWidget!

1.3 MyFirstWidget代碼講解及實用編程技巧分享

現在我們將ui->lineEdit->setText("ThisisMyFirstWidget!");改為ui->lineEdit->setText("你好,Qt!");再運行程序發現顯示的是亂碼。這是文件編碼的問題,在菜單欄選擇:編輯=》Select Encoding...=》UTF-8 按編碼保存,重新運行程序,亂碼問題解決。

1.3 MyFirstWidget代碼講解及實用編程技巧分享


Paste_Image.png

但是,當關閉當前文件,再次打開文件時,仍然是亂碼,此時我們發現Qt仍然使用的是系統默認編碼。解決方法:工具=》選項=》文本編輯器=》行為選項卡=》文件編碼=》默認編碼=》UTF-8,點擊ok。我們關閉文件,再次打開,發現不再是亂碼,問題解決。

1.3.5 編程小技巧

往往好東西都是留在最後滴,接下來給大家介紹一個編程小技巧,如果看不懂,可先做個標記,暫時略過,等待基礎紮實了,再來看這部分內容。現假如需要給MyFirstWidget添加三個成員變量 int value1,int value2,int value3,但不想讓調用者知道我的類有哪些屬性,所以需要把這三個成員變量放到對應的源文件中,那該如何做呢。請看代碼:

<code>頭文件
class MyFirstWidget : public QWidget
{
Q_OBJECT

public:
explicit MyFirstWidget(QWidget *parent = 0);
~MyFirstWidget();

private:
Ui::MyFirstWidget *ui;
//聲明存儲三個變量的結構體Private,並且創建其對應指針
struct Private;
struct Private * d;
};

源文件
//設計Private的好處(至於這個Private也可以換成其它的名詞):
//1. 當在這裡增加了屬性而頭文件沒有改變時,
// 凡是引用myfirstwidget.h的頭文件的文件都不會重新編譯
// 從而加快了編譯速度,尤其遇到大型項目時,這個效果會非常顯著
//2. 利用現在的編程環境,只需要輸入d->,關於這個Private類的所有屬性都會顯示
// 到提示列表中,從而提高了開發速度
//3. 最重要一點,使用這種結構,頭文件會顯得非常整潔,
// 並且如果是提供接口給調用者,他就不會看到是如何實現的了,如果再幹的絕
// 一點,在頭文件中只保留公有接口,其他部分都放到這個類中,那調用者想要從頭

// 文件中推敲點什麼,就是很困難的事了。
// 同時,這也是代碼封裝的一個小技巧哦。
// 關於這個設計,還有缺陷,隨著後面的講解深入小豆君會提供它的改進版,願意思考
// 的知友也可以思考下它還有什麼缺陷。

//內部數據結構體Private定義
struct MyFirstWidget::Private
{
int value1;
int value2;
int value3;

Private(){
value1 = -1;
value2 = -1;
value3 = -1;
}
~Private(){}
};

MyFirstWidget::MyFirstWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyFirstWidget),
d(new Private)
{
ui->setupUi(this);
ui->lineEdit->setText(QString::number(d->value1 + d->value2 + d->value3));
}

MyFirstWidget::~MyFirstWidget()
{
//記得要刪除哦
delete d;
delete ui;
}
/<code>

好了,今天就講到這裡,本節重點熟悉下Qt設計師界面中的所有控件,看看它們都有什麼屬性,試著改變屬性,看控件都有什麼變化。在下一章我就開始講解Qt窗口,OK,我們下期再見。

如果你想第一時間看到我的技術分享,就趕快關注吧。


分享到:


相關文章: