## 7.2 子類化 QDialog
創建基于對話框的應用程序主要是使用子類化 QDialog 的方法。在本節,我們采用這個方法創建一個稍微復雜的實例-可擴展對話框。
可擴展對話框通常只顯示簡單的外觀,但是它還有一個切換按鈕( toggle button), 可以讓用戶在對話框的簡單外觀和擴展外觀之間來回切換。 可擴展對話框通常用于試圖同時 滿足普通用戶和高級用戶需要的應用程序中,這種應用程序通常會隱藏那些高級選項,除非 用戶明確要求看到它們。
這個對話框是一個用于電子制表軟件應用程序的排序對話框( Sort 對話框),在這個 對話框中,用戶可以選擇一列或多列進行排序。在這個簡單外觀中,允許用戶輸入一個單一 的排序鍵,而在擴展外觀下,還額外提供了兩個排序鍵。 More 按鈕允許用戶在簡單外觀和 擴展外觀之間切換。該實例的運行效果如圖 7-2 所示。


圖 7-2 實例運行效果
該實例名為 extensionDlg。共有以下原生源文件:工程文件 extensionDlg.pro,主程 序文件 main.cpp,對話框類 ExtensionDlg 的頭文件 extensionDlg.h,實現文件 extensionDlg.cpp。
在第 6 章中我們向大家介紹了創建 Qt 應用程序的基本方法,這里我們采用 Qt Creator作為 IDE,并使用完全手寫的方式完成程序的界面布局和構建。
首先當然是在 Qt Creator 中創建這個名為 extensionDlg 的項目,類型是 Empty Qt4 Project。然后在其中依次加入對話框類 ExtensionDlg 的頭文件 extensionDlg.h,實現文件 extensionDlg.cpp,主程序文件 main.cpp 以及工程文件 extensionDlg.pro。這些文件的內容, 可以在 Qt Creator 的代碼編輯器中完成編輯。
我們先看一下對話框類 ExtensionDlg 的頭文件的內容。
```
#ifndef EXTENSIONDLG_H
#define EXTENSIONDLG_H
#include <QtGui>
class ExtensionDlg : public QDialog
{
Q_OBJECT
public:
ExtensionDlg();
void initBasicInfo();
void initDetailInfo();
public slots:
void slot2Extension();
private:
QWidget *baseWidget;
QWidget *detailWidget;
};
```
第 1 行引入 QtGui 模塊的頭文件
第 2 行聲明我們的自定義對話框類 ExtensionDlg 單公有繼承自 QDialog。
第 3 行加入 Q_OBJECT 宏,程序中用到諸如信號/槽等 Qt 核心機制的時候,都要加入這 個宏。
第 4-7 行聲明了構造函數和初始化基礎信息和擴展信息的函數。
第 8-9 行聲明公有槽 slot2Extension(),它在用戶點擊【Detail】按鈕時被觸發。
第 10-12 行聲明兩個私有成員變量 baseWidget 和 detailWidget,它們都是 QWidget 的 實例,分別代表伸縮前后的對話框窗體。
再來看看 ExtensionDlg 的實現文件。
```
#include "extensionDlg.h"
ExtensionDlg::ExtensionDlg()
{
setWindowTitle(tr("Extension Dialog"));
initBasicInfo();
initDetailInfo();
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(baseWidget);
layout->addWidget(detailWidget);
layout->setSizeConstraint(QLayout::SetFixedSize);
layout->setSpacing(6);
setLayout(layout);
}
void ExtensionDlg::initBasicInfo()
{
baseWidget = new QWidget;
QLabel *nameLabel = new QLabel(tr("Name"));
QLineEdit *nameEdit = new QLineEdit;
QLabel *sexLabel = new QLabel(tr("Sex"));
QComboBox *sexComboBox = new QComboBox;
sexComboBox->addItem(tr("male"));
sexComboBox->addItem(tr("female"));
QPushButton *okButton = new QPushButton(tr("OK"));
QPushButton *detailButton = new QPushButton(tr("Detail"));
connect(detailButton,SIGNAL(clicked()),this,SLOT(slot2Extension()));
QDialogButtonBox *btnBox = new QDialogButtonBox(Qt::Horizontal);
btnBox->addButton(okButton,QDialogButtonBox::ActionRole);
btnBox->addButton(detailButton,QDialogButtonBox::ActionRole);
QFormLayout *formLayout = new QFormLayout;
formLayout->addRow(nameLabel,nameEdit);
formLayout->addRow(sexLabel,sexComboBox);
QVBoxLayout *vboxLayout = new QVBoxLayout;
vboxLayout->addLayout(formLayout);
vboxLayout->addWidget(btnBox);
baseWidget->setLayout(vboxLayout);
}
void ExtensionDlg::initDetailInfo()
{
detailWidget = new QWidget;
QLabel *ageLabel = new QLabel(tr("Age"));
QLineEdit *ageEdit = new QLineEdit;
ageEdit->setText(tr("25"));
QLabel *deptLabel = new QLabel(tr("Department"));
QComboBox *deptComboBox = new QComboBox;
deptComboBox->addItem(tr("department 1"));
deptComboBox->addItem(tr("department 2"));
deptComboBox->addItem(tr("department 3"));
deptComboBox->addItem(tr("department 4"));
QLabel *addressLabel = new QLabel(tr("address"));
QLineEdit *addressEdit = new QLineEdit;
QFormLayout *formLayout = new QFormLayout;
formLayout->addRow(ageLabel,ageEdit);
formLayout->addRow(deptLabel,deptComboBox);
formLayout->addRow(addressLabel,addressEdit);
detailWidget->setLayout(formLayout);
detailWidget->hide();
}
void ExtensionDlg::slot2Extension()
{
if (detailWidget->isHidden())
{
detailWidget->show();
}
else
{
detailWidget->hide();
}
}
```
第 1-9 句是構造函數中的內容。
第 1 句設置應用程序的標題。
第 2 句調用 initBasicInfo()函數,初始化基本信息船窗體。 第 3 句調用 initDetailInfo()函數,初始化擴展信息窗體。 第 4-9 句設置窗體的布局。
第 4 句定義一個垂直布局類實體 layout。
第 5、6 兩句,分別將 baseWidget 和 detailWidget 加入到布局中。
第 7、8 兩句對于布局管理來說是非常常見的用法,必須熟練掌握。其中 setSizeConstraint()函數用于設置窗體的縮放模式,其默認取值是 QLayout::SetDefaultConstraint。這里取參數值為 Qlayout::SetFixedSize 是為了使窗體 的大小固定,不可經過鼠標拖動而改變大小;如果不這樣設置,當用戶再次點擊 【Detail】按鈕時,對話框將不能恢復到初始狀態。 setSpacing()函數用于設置位于布局之中的窗口部件之間的間隔大小。
這里暫時不對布局管理的相關內容展開講解,在《布局管理》這一章中將有詳細的介紹。
第 9 句將剛剛設置好的布局應用加載到窗體上。
第 10-29 句是 initBasicInfo()函數體的內容。
第 10 句實例化 baseWiaget,注意 baseWidget 是全局變量。
第 11-18 句,依次定義窗體中的部件,注意在輸入字符時,前面都加上了 tr()函數。 第 19 句對于整個程序來說是關鍵,它使用信號 /槽機制連接了 detailButton 的單擊信號和窗口類 ExtensionDlg 的 slot2Extension()函數,這就使得整個對話框變得可伸縮。
第 20-22 行示范了 QDialogButtonBox 類的用法,它用于創建一個符合當前窗口部件樣 式的一組按鈕,并且它們被排列在某種布局之中。在 Qt Designer 中,最為常見的用法是 從窗口部件盒里面把默認的那個 QDialogButtonBox 窗口部件拖到界面上來,不過顯然這并 不如使用代碼來得方便。
第 20 行的 Qt::Horizontal 實參表示創建水平方向的按鈕組合。
第 21、22 兩行把兩個按鈕加入到這個組合之中。其中的 QDialogButtonBox::ActionRole 參數表示創建的按鈕具有實際的功能,單擊它可以引起對話框的某種變化。該參數可以有很 多不同的值,使得這些按鈕具有不同的功能,它們都被包含在 QDialogButtonBox::ButtonRole 這個枚舉值之中。
第 23-29 行設置窗體的布局。窗體的頂級布局是一個垂直布局,而其中嵌套了一個表 單布局。
第 23-25 行是設置表單布局的常用方法,表單布局常用于窗體界面元素可以整齊的分 成兩列的情況。addRow()方法用于向布局中加入整行的界面元素。
第 26-29 行定義窗體的頂級布局,并將其兩個元素 formLayout 和 btnBox 依次加入其中。
小貼士:布局也是一種窗口部件,認識到這一點很關鍵。
第 30-47 行定義了 initDetailInfo()函數。其實現過程與 initBasicInfo()函數大同 小異。只是需要注意第 47 行,正是由于對 detailWidget 調用了 hide()函數,才使得程序 初始時,顯示的是基本信息,而將擴展信息隱藏了起來。 hide()函數用于將窗口隱藏起來, 它是 Qt 默認的槽函數之一,其原型如下:
```
void QWidget::hide () [slot]
```
它的作用等同于調用 setVisible(false)函數。
第 48-55 行定義了 slot2Extension()函數。前面講到,它是我們自定義的槽函數,在 點擊【Detail】按鈕時,將被觸發。它的內容很簡單,就是判斷擴展窗口是否被隱藏,如果被隱藏,就顯示它;否則就隱藏它。 isHidden()函數用于判斷窗體的顯示窗體的顯隱狀態。
然后就可以像下面這樣書寫主函數。第 1 句是必需的。第 2-4 句定義 ExtensionDlg 的 對象,并模態的顯示這個窗體。
```
#include <QApplication>
#include "extensionDlg.h"
int main(int argc, char * argv[])
{
QApplication app(argc,argv);
ExtensionDlg exDlg;
exDlg.show();
return app.exec();
}
```
最后就是書寫項目文件 ExtensionDlg.pro 了。
```
TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .
# Input
HEADERS += extensionDlg.h
SOURCES += extensionDlg.cpp main.cpp
```
第 1 句,表示程序的類型是 app。
第 2 句中 TARGET 指定可執行文件或庫的基本文件名,其中不包含任何的擴展、前綴或 版本號,默認的就是當前的目錄名。
第 4 句中,INCLUDEPATH 指定 C++編譯器搜索全局頭文件的路徑。 第 5 句是注釋。
第 6 句中,HEADERS 指定工程的 C++頭文件(.h)。多個頭文件的情況下,用空格隔 開。
第 7 句中,SOURCES 指定工程的 C++實現文件(.cpp),多個頭文件的情況下,用空格隔開。
qmake 的語法規則是比較簡明的,詳細情況請參閱附錄。 好了,到此我們就完成了使用子類化的方法創建自定義對話框窗口程序。這其中有幾點還想再強調一下,一是要明白所謂子類化自 QDialog 類就是指通過繼承自 QDialog 類來創建自定義的對話框類;二是要知道如果程序中用到了 Qt 的核心機制(如信號/槽),不 要忘記在類的聲明處的第一行加入 Q_OBJECT 宏;三是要掌握判斷和控制顯隱對話框的方法;四是掌握定義窗口界面元素的方法(先定義,再設置其屬性);五是了解布局管理的基本方法(后面還會學到);六是要掌握書寫工程文件的基本方法。七是掌握 Qt Creator 的基本用法。
在下一節,我們將采用 Qt Designer 完成這個程序界面的布局,大家將會了解到,有 時候使用 Qt Designer 設計界面會方便一些。
- 第 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 開發社區