Qt 项目中,后缀为“.ui”的文件是可视化设计的窗体的定义文件,如 widget.ui。双击项目文件目录树中的文件 widget.ui,会打开一个集成在 Qt Creator 中的 Qt Designer 对窗体进行可视化设计,如图 1 所示。 图 1 集成在 Qt Creator中的 UI 设计器 本教程后面将称这个集成在 Qt Creator 中的 Qt Designer 为“UI 设计器”,以便与独立运行的 Qt Designer 区别开来。 图 1 中的 UI 设计器有以下一些功能区域:
图 2 显示的是选中窗体上放置的标签组件后属性编辑器的内容。最上方显示的文字“LabDemo: QLabel”表示这个组件是一个 QLabel 类的组件,objectName 是LabDemo。 图 2 界面组件的属性编辑器 属性编辑器的内容分为两列,分别为属性的名称和属性的值。属性又分为多个组,实际上表示了类的继承关系,如在图 2 中,可以看出 QLabel 的继承关系是 QObject→QWidget→QFrame→QLabel 。objectName 表示组件的对象名称,界面上的每个组件都需要一个唯一的对象名称,以便被引用。界面上的组件的命名应该遵循一定的法则,具体使用什么样的命名法则根据个人习惯而定,主要目的是便于区分和记忆,也要便于与普通变量相区分。 设置其他属性的值只需在属性编辑器里操作即可,如设置 LabDemo 的 text 属性为“Hello,World”,只需像图 2 那样修改 text 属性的值即可。 提示,标准 C++ 语言里并没有 property 关键字,property 是 Qt 对标准 C++ 的扩展,使得在 Qt Designer 里就可以可视化设置类的数据。 在图 1 显示的设计窗体上,放置一个 Label 和一个 Push Button 组件,它们的主要属性设置见表 3。
编辑完属性之后,再为 btnClose 按钮增加一个功能,就是单击此按钮时,关闭窗口,退出程序。使用 Signals 和 Slots 编辑器完成这个功能,如图 4 所示。 图 4 信号与槽编辑器中设计信号与槽的关联 在信号与槽编辑器的工具栏上单击“Add”按钮,在出现的条目中,Sender 选择 btnClose,Signal 选择 clicked(),Receiver 选择窗体 Widget,Slot 选择 close()。这样设置表示当按钮 btnClose 被单击时,就执行 Widget 的 close() 函数,实现关闭窗口的功能。 然后对项目进行编译和运行,可以出现如图 5 所示的窗口,单击“Close”按钮可以关闭程序。 图 5 具有 Close 按钮的“Hello World”程序 标签的文字内容和字体被修改了,窗口标题也显示为所设置的标题,而我们并没有编写一行程序语句,Qt 是怎么实现这些功能的呢? 为了搞清楚窗体类的定义,以及界面功能的实现原理,这里将项目进行编译。编译后在项目目录下会自动生成一个文件 ui_widget.h,这样对于一个窗体,就有 4 个文件了,各文件的功能说明见表 6。
下面分别分析各个文件的内容及其功能,以及它们是如何联系在一起工作,实现界面的创建与显示的。 widget.h 文件widget.h 文件是窗体类的头文件。在创建项目时,选择窗体基类是 QWidget,在 widget.h 中定义了一个继承自 QWidget 的类 Widget。下面是 widget.h 文件的内容: #ifndef WIDGET_H#define WIDGET_H#include <QWidget>namespace Ui {class Widget;}class Widget : public QWidget{ Q_OBJECTpublic: explicit Widget(QWidget *parent = 0); ~Widget();private: Ui::Widget *ui;};#endif // WIDGET_H widget.h 文件有几个重要的部分。namespace 声明代码中有如下的一个 namespace 声明:namespace Ui {class Widget;}这是声明了一个名称为 Ui 的命名空间(namespace),包含一个类 Widget。但是这个类 Widget 并不是本文件里定义的类 Widget,而是 ui_widget.h 文件里定义的类,用于描述界面组件的。这个声明相当于一个外部类型声明(具体要看完 ui_widget.h 文件内的解释之后才能搞明白)。 Widget 类的定义widget.h 文件的主体部分是一个继承于 QWidget 的类 Widget 的定义,也就是本实例的窗体类。在 Widget 类中使用了宏 Q_OBJECT,这是使用 Qt 的信号与槽(signal 和 slot)机制的类都必须加入的一个宏(信号与槽在后面详细介绍)。 在 public 部分定义了 Widget 类的构造函数和析构函数。 在 private 部分又定义了一个指针。 Ui::Widget *ui; 这个指针是用前面声明的 namespace Ui 里的 Widget 类定义的,所以指针 ui 是指向可视化设计的界面,后面会看到要访问界面上的组件,都需要通过这个指针 ui。widget.cpp 文件widget.cpp 文件是类 Widget 的实现代码,下面是 widget.cpp 文件的内容。#include 'widget.h'#include 'ui_widget.h'Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this);}Widget::~Widget(){ delete ui;} 注意到,在这个文件的包含文件部分自动加入了如下一行内容:#include 'ui_widget.h' 这个就是 Qt 编译生成的与 UI 文件 widget.ui 对应的类定义文件。目前只有构造函数和析构函数。其中构造函数头部是: Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) 其意义是:执行父类 QWidget 的构造函数,创建一个 Ui::Widget 类的对象 ui。这个 ui 就是 Widget 的 private 部分定义的指针变量 ui。构造函数里只有一行语句: ui->setupUi(this) 它是执行了 Ui::Widget 类的 setupUi() 函数,这个函数实现窗口的生成与各种属性的设置、信号与槽的关联(后面会具体介绍)。析构函数只是简单地删除用 new 创建的指针 ui。 所以,在 ui_widget.h 文件里有一个 namespace 名称为 Ui,里面有一个类 Widget 是用于描述可视化设计的窗体,且与 widget.h 里定义的类同名。在 Widget 类里访问 Ui::Widget 类的成员变量或函数需要通过 Widget 类里的 ui 指针,如同构造函数里执行 ui->setupUi( this) 函数那样。 widget.ui 文件widget.ui 是窗体界面定义文件,是一个 XML 文件,定义了窗口上的所有组件的属性设置、布局,及其信号与槽函数的关联等。用UI设计器可视化设计的界面都由 Qt 自动解析,并以 XML 文件的形式保存下来。在设计界面时,只需在 UI 设计器里进行可视化设计即可,而不用管 widget.ui 文件是怎么生成的。下面是 widget.ui 文件的内容: <?xml version='1.0' encoding='UTF-8'?><ui version='4.0'><class>Widget</class><widget class='QWidget' name='Widget'> <property name='geometry'> <rect> <x>0</x> <y>0</y> <width>336</width> <height>216</height> </rect> </property> <property name='windowTitle'> <string>My First Demo</string> </property> <widget class='QLabel' name='Lablabel'> <property name='geometry'> <rect> <x>100</x> <y>70</y> <width>141</width> <height>61</height> </rect> </property> <property name='font'> <font> <pointsize>12</pointsize> <weight>75</weight> <bold>true</bold> </font> </property> <property name='text'> <string>Hello,World</string> </property> </widget> <widget class='QPushButton' name='btnClose'> <property name='geometry'> <rect> <x>210</x> <y>150</y> <width>75</width> <height>23</height> </rect> </property> <property name='text'> <string>Close</string> </property> </widget></widget><layoutdefault spacing='6' margin='11'/><resources/><connections> <connection> <sender>btnClose</sender> <signal>clicked()</signal> <receiver>Widget</receiver> <slot>close()</slot> <hints> <hint type='sourcelabel'> <x>247</x> <y>161</y> </hint> <hint type='destinationlabel'> <x>167</x> <y>107</y> </hint> </hints> </connection></connections></ui> ui_widget.h 文件ui_widget.h 是在对 widget.ui 文件编译后生成的一个文件,ui_widget.h 会出现在编译后的目录下,或与 widget.ui 同目录(与项目的 shadow build 编译设置有关)。文件 ui_widget.h 并不会出现在 Qt Creator 的项目文件目录树里,当然,可以手工将 ui_widget.h 添加到项目中。方法是在项目文件目录树上,右击项目名称节点,在调出的快捷菜单中选择“Add Existing Files…”,找到并添加 ui_widget.h 文件即可。 注意,ui_widget.h 是对 widget.ui 文件编译后自动生成的,widget.ui 又是通过 UI 设计器可视化设计生成的。所以,对 ui_widget.h 手工进行修改没有什么意义,所有涉及界面的修改都应该直接在UI 设计器里进行。所以,ui_widget.h 也没有必要添加到项目里。 下面是 ui_widget.h 文件的内容: /********************************************************************************** Form generated from reading UI file 'widget.ui'**** Created by: Qt User Interface Compiler version 5.9.1**** WARNING! All changes made in this file will be lost when recompiling UI file!********************************************************************************/#ifndef UI_WIDGET_H#define UI_WIDGET_H#include <QtCore/QVariant>#include <QtWidgets/QAction>#include <QtWidgets/QApplication>#include <QtWidgets/QButtonGroup>#include <QtWidgets/QHeaderView>#include <QtWidgets/QLabel>#include <QtWidgets/QPushButton>#include <QtWidgets/QWidget>QT_BEGIN_NAMESPACEclass Ui_Widget{public: QLabel *label; QPushButton *btnClose; void setupUi(QWidget *Widget) { if (Widget->objectName().isEmpty()) Widget->setObjectName(QStringLiteral('Widget')); Widget->resize(336, 216); label = new QLabel(Widget); label->setObjectName(QStringLiteral('label')); label->setGeometry(QRect(100, 70, 141, 61)); QFont font; font.setPointSize(12); font.setBold(true); font.setWeight(75); label->setFont(font); btnClose = new QPushButton(Widget); btnClose->setObjectName(QStringLiteral('btnClose')); btnClose->setGeometry(QRect(210, 150, 75, 23)); retranslateUi(Widget); QObject::connect(btnClose, SIGNAL(clicked()), Widget, SLOT(close())); QMetaObject::connectSlotsByName(Widget); } // setupUi void retranslateUi(QWidget *Widget) { Widget->setWindowTitle(QApplication::translate('Widget', 'My First Demo', Q_NULLPTR)); label->setText(QApplication::translate('Widget', 'Hello\357\274\214World', Q_NULLPTR)); btnClose->setText(QApplication::translate('Widget', 'Close', Q_NULLPTR)); } // retranslateUi};namespace Ui { class Widget: public Ui_Widget {};} // namespace UiQT_END_NAMESPACE#endif // UI_WIDGET_H 查看 ui_widget.h 文件的内容,发现它主要做了以下的一些工作:
相关文件推荐:
|
|
来自: goodwangLib > 《QT》