## 10.3 編譯時加入處理.ui 文件的方法
編譯時加入處理.ui 文件通常可以采用 3 種方式:直接使用法、單繼承法和多繼承法。 下面我們就以 Calculator Form 這個程序為例,分別介紹這 3 種方式的使用。 Calculator Form 程序主要實現了簡單的加法計算功能,在 Qt Designer 中繪制的用戶界面如圖 10-2 所示。

圖 10-2 Calculator Form 的.ui 文件
### 10.3.1 直接使用法
本小節例子的代碼是來自源碼包中的 calculatorform-direct 實例。
1\.使用要點
這種方法的要領是創建一個子類化 QWidget 的自定義類,把它作為“容器”來存放在 calculatorform.ui 中描繪的窗體。
2\.實例講解
我們的應用程序工程中通常包含一個 main.cpp 文件以及一個.ui 文件。 如果全部采用手寫代碼的話,我們需要在 qmake 工程文件.pro 中加入幾行:
```
TEMPLATE = app
FORMS = calculatorform.ui
SOURCES = main.cpp
```
第 2 句告訴 qmake 使用 uic 編譯 calculatorform.ui 文件,這將生成
ui_calculatorform.ui 文件,通過前面對該文件內容的分析,我們知道這個文件中有一個界 面實體類,其中包含所有的界面元素的描述和配置情況 ,并且 qmake 為我們生成了一個單公有繼承自這個界面實體類的一個子類 - CalculatorForm,它位于 Ui 名字空間中。
qmake 將據此生成 ui_calculatorform.h 文件,我們需要在 SOURCES 變量中列出的文件 加入這個文件的聲明(這里只有 main.cpp 文件):
```
#include "ui_calculatorform.h"
```
在 main()函數中我們創建了一個標準的 QWidget 實例,并把它作為容器用來“存放”在 calculatorform.ui 中描述的窗體。
```
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget *widget = new QWidget;
Ui::CalculatorForm ui;
ui.setupUi(widget);
widget->show();
return app.exec();
}
```
Ui:: CalculatorForm 即是單公有繼承自界面實體類的子類,它繼承了界面實體類的公有方法 setupUi(),我們調用它實現界面元素的布置。
運行一下這個程序,大家就會發現問題了,它并沒有完成加法計算的功能。這種方法的 局限性暴露了出來,由于在 Qt4 中,Qt Designer 只能完成基本的系統內置的信號與槽的連 接功能,而不再提供代碼編輯功能,那么我們需要自定義信號和槽時,往往就無能為力了。 這就需要使用單繼承法和多繼承法來實現與用戶的交互,因為它們可以通過代碼操縱窗體元 素。
### 10.3.2 單繼承法
本小節例子的代碼是來自源碼包中的 calculatorform 實例。
1\.使用要點
這種做法的要領是,子類化窗體的基類(如 QWidget 或者 QDialog 等),并在該自定義 類中定義一個私有(private)成員變量,該變量是由 uic 工具生成的基于 Qt Designer 生成 的.ui 文件的界面類的實例,其形式為:
```
private: Ui_YourFormName ui
```
或者:
```
private:Ui::YourFormName ui
```
接下來,在該自定義類的構造函數中構造和初始化界面元素(使用 setupUi()函數),這之后,便可以通過實例 ui 來使用界面中的各個部件。

圖 10-3 單繼承方式的類關系圖
2\.實例講解
我們仍然以 Calculator Form 為例,講解這種方式的用法。首先介紹完全手寫代碼的方 法,了解了這個后,你可以嘗試在 IDE 里面如 Qt Creator 來完成,這就比較容易了。
在引用 Ui::CalculatorForm 之前,我們需要加入由 uic 生成的 C++頭文件的聲明:
```
#include "ui_calculatorform.h"
```
在工程文件中也要加入 calculatorform.h 這個頭文件:
```
HEADERS = calculatorform.h
```
現在看一下我們這個子類的聲明:
```
class CalculatorForm : public QWidget
{
Q_OBJECT
public:
CalculatorForm(QWidget *parent = 0);
private slots:
void on_inputSpinBox1_valueChanged(int value);
void on_inputSpinBox2_valueChanged(int value);
private:
Ui::CalculatorForm ui;
};
```
第 1 行聲明了 CalculatorForm 這個類公有繼承自 QWidget,接下來第 9、10 兩行聲明了一個私有的 ui 變量,以后就由它來完成對應用程序界面的創建 、布置以及信號與槽的關聯。再看看構造函數:
```
CalculatorForm::CalculatorForm(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
}
```
前面講過,setupUi()是重要的函數,我們一般在類的構造函數中調用它,由它來完成窗體的界面元素的布局和設置。
接下來,就可以使用 ui 變量來訪問界面元素了,請看下面的示例代碼:
```
void CalculatorForm::on_inputSpinBox1_valueChanged(int value)
{
ui.outputWidget->setText(QString::number(value + ui.inputSpinBox2->value()));
}
```
這種方式的優點是,應用程序能夠控制用戶界面的外觀和顯示方式 ,并能夠與用戶進行交互;此外,還可以使用同樣的一個 .ui 文件來生成多個不同的自定義界面類,也就是可以 重用 Qt Designer 繪制的用戶界面。尤其是當我們需要由一個已經存在的用戶界面上派生出多個類似的界面類時,這種方法非常有效。
### 10.3.3 多繼承法
本小節例子的代碼是來自源碼包中的 multipleinheritance 實例。
1\.使用要點
這種做法的要領是,從使用 Qt Designer 設計的界面實體類(Ui::YourFormName)和 QWidget 或者 QDialog 及其子類中多繼承派生一個自定義界面類,其形式為:
```
class myWidget : public QWidget,public Ui_YourFormName
{
Q_OBJECT
public:
myWidget( QWidget *widget = 0 );
}
```
或者這樣寫:
```
class myWidget : public QWidget,public Ui::YourFormName
{
Q_OBJECT
public:
myWidget( QWidget *widget = 0 );
}
```
這樣,我們就可以在 myWidget 這個子類中直接使用界面類的成員,也可以顯式的設置信號與槽的連接。比如你在界面中布置了一個 pushButton 類,它的 ObjectName 屬性為 pushButton。那么,在程序中就可以這樣使用:
```
pushButton->setText(tr(“Add”));
```
大家看看,是不是非常的簡便。下面這張 UML 圖顯示了多繼承法中的類關系圖。

圖 10-4 多繼承方式-類關系圖
2\.實例講解
我們這個實例名叫 Multiple Inheritance ,完成簡單的加法計算功能,.ui 界面文 件與前述相同。
先來看看 calculatorform.h 頭文件中的內容:
```
#include "ui_calculatorform.h"
class CalculatorForm : public QWidget, private Ui::CalculatorForm
{
Q_OBJECT
public:
CalculatorForm(QWidget *parent = 0);
private slots:
void on_inputSpinBox1_valueChanged(int value);
void on_inputSpinBox2_valueChanged(int value);
};
```
首先需要加入由 uic 根據 calculatorform.ui 生成的 ui_calculatorform.h 頭文件,因為我們自定義的 CalculatorForm 類的基類之一的 Ui::CalculatorForm 是在該文件中定義的。 在這里我們選擇私有繼承自 Ui::CalculatorForm 的原因是,以后不準備再以 CalculatorForm 類為基類來創建派生類,因而需要確保界面元素保持私有。當然,你也可以選擇公有或者保 護繼承,那么就可以再以 CalculatorForm 為基類,繼續派生。
接下來與使用單繼承方式類似的,我們在構造函數中調用 setupUi()方法完成界面元素 的初始化和布局。
```
CalculatorForm::CalculatorForm(QWidget *parent)
: QWidget(parent)
{
setupUi(this);
}
```
接下來,我們可以像前幾章中介紹的完全用手寫代碼的方式創建窗體那樣直接訪問界面元素,而無需 ui 前綴了,請看下面的示例代碼:
```
void CalculatorForm::on_inputSpinBox1_valueChanged(int value)
{
outputWidget->setText(QString::number(value + inputSpinBox2->value()));
}
void CalculatorForm::on_inputSpinBox2_valueChanged(int value)
{
outputWidget->setText(QString::number(value + inputSpinBox1->value()));
}
```
主函數可以這樣編寫:
```
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
CalculatorForm calculator;
calculator.show();
return app.exec();
}
```
在 main()函數中,我們依次實例化 QApplication 和 CalculatorForm 的對象,然后調用 show()函數來顯示窗體。
從以上對 3 種繼承方式的分析可見,多繼承方式可直接對 ui 頁面上的控件或函數進行 操作調用,代碼編寫更加清晰、簡潔;而使用單繼承方式,在操作 ui 頁面上的控件時需要 加上 ui 對象前綴,編寫代碼較為繁瑣。但對于程序中所需用到的 ui 頁面較多時,使用單繼 承方式則要簡便很多。因此,在實現較為復雜的多窗口程序時,可以優先考慮使用單繼承法。 而直接使用法一般采用的比較少。
- 第 1 章 走近 Qt
- 1.1 Qt 簡介
- 1.2 Qt 紀事概覽
- 1.3 Qt 套件的組成(以 Qt4.5 為準)
- 1.4 Qt 的授權
- 1.5 Qt 的產品
- 1.6 Qt 的服務與支持
- 1.7 Qt 的最新進展
- 1.8為什么選擇 Qt
- 1.9 問題與解答
- 1.10 總結與提高
- 第 2 章 Qt 的安裝與配置
- 2.1 獲取 Qt
- 2.2 協議說明
- 2.3 安裝 Qt
- 2.4 配置 Qt4 環境
- 2.5 問題與解答
- 2.6 總結與提高
- 第 3 章 Qt 編程基礎
- 3.1 標準 C++精講
- 3.2 Windows 編程基礎
- 3.3 Linux 編程基礎
- 3.4 Mac 編程基礎
- 3.5 問題與解答
- 3.6 總結與提高
- 第 4 章 Qt 4 集成開發環境
- 4.1 常見的 Qt IDE
- 4.2 Qt Creator
- 4.3 Eclipse
- 4.5 問題與解答
- 4.6 總結與提高
- 第 5 章 使用 Qt 基本 GUI 工具
- 5.1 使用 Qt Designer 進行 GUI 設計
- 5.2 使用 Qt Assistant 獲取在線文檔與幫助
- 5.3 使用 Qt Demo 學習 Qt 應用程序開發
- 5.4 問題與解答
- 5.5 總結與提高
- 第 6 章 Qt 4 程序開發方法和流程
- 6.1 開發方法
- 6.2 Hello Qt
- 6.3 幾個重要的知識點
- 6.4 問題與解答
- 6.5 總結與提高
- 第 7 章 對話框
- 7.1 QDialog 類
- 7.2 子類化 QDialog
- 7.3 快速設計對話框
- 7.4 常見內建(built in)對話框的使用
- 7.5 模態對話框與非模態對話框
- 7.6 問題與解答
- 7.7 總結與提高
- 第 8 章 主窗口
- 8.1 主窗口框架
- 8.2 創建主窗口的方法和流程
- 8.3 代碼創建主窗口
- 8.4 使用 Qt Designer 創建主窗口
- 8.5 中心窗口部件專題
- 8.6 Qt4 資源系統專題
- 8.7 錨接窗口
- 8.8 多文檔
- 8.9 問題與解答
- 8.10 總結與提高
- 第 9 章 Qt 樣式表與應用程序觀感
- 9.1 應用程序的觀感
- 9.2 QStyle 類的使用
- 9.3 樣式表概述
- 9.4 使用樣式表
- 9.5 問題與解答
- 9.6 總結與提高
- 第 10 章 在程序中使用.ui 文件
- 10.1 uic 的使用
- 10.2 Ui_YourFormName.h 文件的組成
- 10.3 編譯時加入處理.ui 文件的方法
- 10.4 運行時加入處理.ui 文件的方法
- 10.5 信號與槽的自動連接
- 10.6 問題與解答
- 10.7 總結與提高 本章主要講解了以下內容:
- 第 11 章 布局管理
- 11.1 基本概念和方法
- 11.2在 Qt Designer 中使用布局
- 11.3 基本布局實踐
- 11.4 堆棧布局
- 11.5 分裂器布局
- 11.6 自定義布局管理器
- 11.7 布局管理經驗總結
- 11.8 問題與解答
- 11.9 總結與提高
- 第 12 章 使用 Qt Creator
- 12.1 Qt Creator 概覽
- 12.2 Qt Creator 的組成
- 12.3 快捷鍵和常用技巧
- 12.4 Qt Creator 構建系統的設置
- 12.5 處理項目間依賴關系( Dependencies )
- 12.6 Qt 多版本共存時的管理
- 12.7 使用定位器在代碼間快速導航
- 12.8 如何創建一個項目
- 12.9 實例講解
- 12.10 使用 Qt Creator 調試程序
- 12.11 問題與解答
- 12.12 總結與提高
- 第 13 章 Qt 核心機制與原理
- 13.1 Qt 對標準 C++的擴展
- 13.2 信號與槽
- 13.3 元對象系統
- 13.4 Qt 的架構
- 13.5 Qt 的事件模型
- 13.6 構建 Qt 應用程序
- 13.7 總結與提高
- 附錄 A qmake 使用指南
- A.1 qmake 簡介
- A.2 使用 qmake
- 附錄 B make 命令
- B.1 命令解釋
- B.2 使用 make 自動構建
- 附錄 C Qt 資源
- C.1Qt 官方資源
- C.2 Qt 開發社區