## 10.3 编译时加入处理.ui 文件的方法
编译时加入处理.ui 文件通常可以采用 3 种方式:直接使用法、单继承法和多继承法。 下面我们就以 Calculator Form 这个程序为例,分别介绍这 3 种方式的使用。 Calculator Form 程序主要实现了简单的加法计算功能,在 Qt Designer 中绘制的用户界面如图 10-2 所示。
![](https://box.kancloud.cn/2016-01-22_56a1a1575ed32.png)
图 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 来使用界面中的各个部件。
![](https://box.kancloud.cn/2016-01-22_56a1a15776828.png)
图 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 图显示了多继承法中的类关系图。
![](https://box.kancloud.cn/2016-01-22_56a1a1578450c.png)
图 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 开发社区