7.3 快速设计对话框

(续上面的例子,使用 Qt Designer 设计界面) 在这一节中将通过使用 Qt Designer 来创建与上一节相同的可扩展对话框 ,并且使用 Qt Creator 作为 IDE 来管理这个工程。

我们将在 Qt Designer 中创建这个对话框的扩展外观,并且在运行时根据需要隐藏 扩 展信息。这个窗口看起来有些复杂,但在 Qt Designer 中可以轻易的完成它。

第 1 步,新建 Qt Creator 工程。

首先启动 Qt Creator,依次单击菜单项【File】->【New】,在弹出的对话框中选择工 程类型为【Empty Qt4 Project】,如图 7-3 所示。点击【Next】按钮进入下一步。

图 7-3 创建新工程

然后,像图 7-4 那样设置工程名称和存放的路径(根据自己的情况调整)。点击【Next】按钮进入下一步。

图 7-4 设置项目名称和存放的位置

在弹出的如图 7-5 所示的对话框中,点击【Finish】按钮完成工程的创建。

图 7-5 完成工程的创建

第 2 步,启动 Qt Designer,新建窗体。

依次单击菜单【File】->【New Form】,如图 7-6 所示,在【新建窗体】对话框中选 择【Dialog without Buttons】模板。

图 7-6 第 2 步 新建窗体

第 3 步,创建【基本信息】窗体的界面元素。

创建一个 GroupBox 部件,使它足够大,将它的 objectName 属性修改为 basicGroupBox,将它的 title 属性设置为 Basic。

接下来在 basicGroup 部件的内部创建下述的各个部件。 创建【Name】和【Sex】标签,使它们上下排列,将它们的 objectName 属性分别设置为 nameLabel 和 sexLabel,将它们的 text 属性分别设置为 Name 和 Sex。

再创建 Name 标签对应的编辑框,从窗口部件盒中拖出 LineEdit 控件。把它的 objectName 属性设置为 nameLineEdit。

创建 Sex 标签对应的组合框,从窗口部件盒中拖出 ComboBox 窗口部件,把它的 objectName 属性设置为 sexComboBox。

接下来为 Sex 标签对应的组合框创建列表项,方法是双击该组合框,如图 7-7 所示,在【编辑组合框】对话框中添加。

图 7-7 编辑组合框

创建【OK】按钮并把它拖放到【Sex】标签的下方。将它的 objectName 属性修改为 okButton,并将它的 defaults 属性设置为 true。

创建【Detail】按钮并将它拖放到 OK 按钮的水平右方,将它的 objectName 属性修改 为 detailButton,并将它的 defaults 属性设置为 true。

接下来,再创建一个垂直分隔符并把它拖放到 【Basic】分组框的下方。 不必刻意调整各个窗口部件的位置,只需大致排列一下即可。布置好后的情形如图 7-8所示。

图 7-8 第 3 步 创建基本信息窗体的界面元素

第 4 步,设置【基本信息】窗体的布局。

单击【OK】按钮,按下 Shift 键后再单击【Detail】按钮,然后单击工具栏上的【Lay Out Horizontally】按钮,设置一个水平布局。

选中【Name】和【Sex】标签,以及它们对应的 LineEdit 窗口部件,然后单击工具栏 上的【Lay Out In a Form】按钮,设置为表单布局。

最后点击【Basic】分组框,然后单击工具栏上的【Lay Out Vertically】按钮,设置一个垂直布局。

设置到这里的界面情形如图 7-9 所示。

图 7-9 第 4 步 基本信息界面布局

第 5 步,创建【扩展信息】窗体界面元素。 拖动窗体的右下角,使其足够高和宽,以便能够容纳所有的界面元素。 创建一个 GroupBox 部件,使它足够大,将它的 objectName 属性修改为 extensionGroupBox,将它的 title 属性设置为 Extension。

像创建【基本信息】窗体界面元素那样,依次创建 Age 标签、Department 标签、 Address 标签以及和它们对应的 LineEdit 和 ComboBox,并把它们放入到 extensionGroupBox 分组框之中。

为 Department 标签对应的 ComboBox 添加列表项。 这样设置后的界面情形如图 7-10 所示。

图 7-10 第 4 步 设置【扩展信息】窗体界面元素。

第 6 步,设置【扩展信息】窗体布局。

选中【Age】、【Department】和【Adress】标签,以及它们对应的编辑框、组合框窗 口部件,然后单击工具栏上的【Lay Out In a Form】按钮,设置为表单布局。

选中【Extension】分组框,然后单击工具栏上的【Lay Out Vertically】按钮,设置 为垂直布局,如图 7-11 所示。

图 7-11 第 6 步 设置【扩展信息】信息窗体布局

第 7 步,设置窗体的顶级(Top Level)布局。 用鼠标左键点击窗体,注意不要选中任何窗口部件,然后单击工具栏上的 【Lay Out Vertically】按钮,设置窗体的顶级布局为一个垂直布局,如图 7-12 所示。

图 7-12 第 7 步 设置窗体的顶级布局

小贴士:如果没能生成你所希望的那种布局效果,或者是不小心做错了,那么总是可以随时先通过单击菜单项【Edit】->【Unto】,或者是【Form】->【Break Layout】,然后再重 新放置这些要摆放的窗口部件,最后试着对它们重新布局,直到满意为止。

第 8 步,设置 Tab 顺序。

单击菜单项【编辑】->【编辑 Tab 顺序】,或者点击工具栏上对应的按钮,像图 7-13 所示那样编辑 Tab 顺序。

图 7-13 第 8 步 设置 Tab 顺序

第 9 步,设置信号/槽

按下 F3 键,离开 Tab 顺序设置模式,进入窗口编辑模式。 现在,窗体设计已经完成,可以开始着手设置一些信号 /槽的连接来实现窗体的功能了。Qt Designer 允许我们在构成同一窗体的不同部分内的窗口部件之间建立连接。我们需要建立两个连接。

单击菜单项【编辑】->【编辑信号/槽】,或者按下 F4 键,进入 Qt Designer 的信号- 槽连接设置模式。窗体中各个窗口部件之间的连接用蓝色箭头表示,如图 7-14 所示。并且 它们也会同时在 Qt Designer 的信号/槽编辑器窗口中显示出来。

图 7-14 窗体中各个部件的连接是蓝色的线

小贴士:要在两个窗口部件之间建立连接,可以单击作为发射器的窗口部件并且拖动所产 生的红色箭头线到作为接收器的窗口部件上,然后松开鼠标按键。这时会弹出一个对话框, 可以从中选择建立连接的信号和槽。

要建立的第一个连接位于 okButton 按钮和窗体的 accept()槽之间。把从 okButton 按 钮开始的红色箭头线拖动到窗体的空白区域,然后松开按键,这样会弹出图所示的设置连接 对话框(Configure Connection dialog)。从该对话框中选择 clicked()作为信号,选择 accept()作为槽,然后单击 OK 按钮,如图 7-15 所示。

图 7-15 连接按钮的 clicked()信号和窗体的 accept()槽

要建立的第 2 个连接位于【Detail】按钮和【extensionGroupBox】群组框之间。在这 两个窗口部件之间拖动红色箭头线,然后选择 toggled(bool)作为信号,选择 setVisible(bool)作为槽,如图 7-15 所示。

图 7-15 连接按钮的 toggled(bool)槽和分组框的 setVisible(bool)槽

小贴士:默认情况下,setVisible(bool)槽不会显示在 Qt Designer 的槽列表中,但是选 中了【显示从 Qwidget 继承的信号和槽】选项,就可以看到这个槽了。

最后设置完成的信号和槽如图 7-16 所示。

图 7-16 设置完成的信号和槽的情形

第 10 步,保存文件。

将这个对话框保存在前面建立的工程目录下,即 extensionDlgDesigner 目录里面,文 件名为 extensionDlgDesigner.ui。接下来要给这个窗体添加代码,将使用多重继承的方法。

首先用如下内容创建一个 extensionDlg.h 文件:

#ifndef EXTENSIONDLG_H
#define EXTENSIONDLG_H
#include <QDialog>
#include "ui_extensionDlg.h"
Class ExtensionDlg:public QDialog,public Ui::Dialog
{
    Q_OBJECT
public:
    ExtensionDlg(QWidget *parent = 0);
};
#endif

这里采用的是多重继承的方法,而 Q_OBJECT 宏则是必需的,并且要放在类声明体内最为靠前的地方。

然后再创建 extension.cpp 文件,以下是其内容:

#include <QtGui>
#include "extensionDlg.h"
ExtensionDlg::ExtensionDlg(QWidget *parent)
:QDialog(parent)
{
    setupUi(this);
    this->extensionGroupBox->hide();
    mainVerticalLayout->setSizeConstraint(QLayout::SetFixedSize);
}

第 1 行调用 setupUi()函数初始化窗体界面元素的布局。

第 2 行表示隐藏了扩展信息窗体,直到用户点击了 【Detail】按钮才显示出来。

第 3 行把窗体布局的 sizeConstraint 属性设置为 QLayout::SetFixedSize,这样会使 用户不能再重新修改这个对话框窗体的大小。前面也讲过,这样一来,布局就会负责对话框 重新定义大小的职责,并且也会在显示或者隐藏子窗口部件的时候自动重新定义这个对话框 的大小,从而可以确保对话框总是能以最佳的尺寸显示出来。

最后用下面的代码创建 main()函数,主要就是显示这个对话框。

#include "extensionDlg.h"
#include <QApplication>
int main(int argc,char *argv[])
{
    QApplication app(argc,argv);
    ExtensionDlg *dlg = new ExtensionDlg;
    dlg->show();
    return app.exec();
}

添加完这些文件后,可以看看工程文件 extensionDlgDesigner.pro 的内容,这是 Qt Creator 根据程序的情况自动为我们添加好的。

HEADERS += extensionDlg.h
SOURCES += extensionDlg.cpp \
main.cpp
FORMS += extensionDlgDesigner.ui

程序最后的运行效果如图 7-17 所示,可以看出与手动编写代码的情形是一致的。

图 7-17 程序运行效果

到此,关于扩展对话框的构建就讲解完了。设计一个扩展对话框并不比设计一个简单 对话框困难:所需要的就是一个切换按钮、一些信号 -槽连接以及一个不可以改变尺寸大小 的布局。

小贴士:在实际的应用程序中,控制扩展对话框的按钮通常会在只显示了基本对话框时显 示为 Advanced>>,而在显示了扩展对话框时才显示为 Advanced<<。这在 Qt 中非常容易实 现,只需在单击这个按钮时调用 QPushButton 的 setText()函数即可。

通过这个例子,我们讲述了通过子类化构建自定义对话框的方法,以及使用 Qt Designer 辅助设计对话框的方法,在工程实践中,这两种方法往往是结合使用的。

扩展阅读:在 Qt 中,无论是使用手工编码的方式还是使用 Qt Designer,都可以轻松的创建另一种常用的可以改变形状的对话框:多页对话框。可以通过多种不同的方式创建这种对话框:

QTabWidget 的用法就像它自己的名字一样。它提供了一个可以控制内置 QStackedWidget 的 Tab 栏。

QListWidget 和 QStackedWidget 可以一起使用,将 QListWidget::currentRowChanged()信号与 QStackedWidget::setCurrentIndex()槽连接, 然后再利用 QListWidget 的当前项就可以确定应该显示 QStackedWidget 中的哪一页。

与上述 QListWidget 的用法相似,也可以将 QTextWidget 和 QStackedWidget 一起 使用。

在后面的《布局管理》一章中,我们将讲解 QStackedWidget 类。