## 7.2 子类化 QDialog
创建基于对话框的应用程序主要是使用子类化 QDialog 的方法。在本节,我们采用这个方法创建一个稍微复杂的实例-可扩展对话框。
可扩展对话框通常只显示简单的外观,但是它还有一个切换按钮( toggle button), 可以让用户在对话框的简单外观和扩展外观之间来回切换。 可扩展对话框通常用于试图同时 满足普通用户和高级用户需要的应用程序中,这种应用程序通常会隐藏那些高级选项,除非 用户明确要求看到它们。
这个对话框是一个用于电子制表软件应用程序的排序对话框( Sort 对话框),在这个 对话框中,用户可以选择一列或多列进行排序。在这个简单外观中,允许用户输入一个单一 的排序键,而在扩展外观下,还额外提供了两个排序键。 More 按钮允许用户在简单外观和 扩展外观之间切换。该实例的运行效果如图 7-2 所示。
![](https://box.kancloud.cn/2016-01-22_56a1a150bc9a7.png)![](https://box.kancloud.cn/2016-01-22_56a1a150cd02c.png)
![](https://box.kancloud.cn/2016-01-22_56a1a150dd075.png)
图 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 开发社区