完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1、概述 Qt 允许程序员不通过任何设计工具,以纯粹的 C++代码来设计一个程序。但是更多的 程序员更加习惯于在一个可视化的环境中来设计程序,尤其是在界面设计的时候。这是因为 这种设计方式更加符合人类思考的习惯,也比书写代码要快速的多。 Qt 也提供了这样一个可视化的界面设计工具:Qt 设计器(Qt Designer)。其开始界面 如上图所示。Qt 设计器可以用来开发一个应用程序全部或者部分的界面组件。以 Qt 设计器 生成的界面组件最终被变成 C++代码,因此 Qt 设计器可以被用在一个传统的工具链中,并 且它是编译器无关的。 在不同的平台上启动 Qt Designer 的方式有一定差别。在 Windows 环境下你可以在“开 始->程序->Qt”这个组件中找到 Qt Designer 的图标并点击;在 Unix 环境下,在命令行模式 下输入命令: “designer”;在 Mac Os 下,在 X Finder 下双击 Designer 图标。 默认情况下,Qt Designer 的用户界面是由几个顶级的窗口共同组成的。如果你更习惯 于一个 MDI-style 的界面(由一个顶级窗口和几个子窗口组成的界面),可以在菜单 Edit->User Interface Mode 中选择 Docked Window 来切换界面。上图显示的就是 MDI-style 的界面风格。 2、开始学习 在这个小节中,我们将使用 Qt Designer 来生成一个对话框: Go-to-cell。对话框如下图 所示。 不管我们是使用 Qt Designer 还是编码来实现一个对话框,都包括以下相同的步骤: 1)、创建并初始化子窗口部件。 2)、将子窗口部件放置到布局当中。 3)、对 Tab 的顺序进行设置。 4)、放置信号和槽的连接。 5)、完成对话框的通用槽的功能。 现在开始工作。首先在 Qt Designer 的菜单中选择“File->New Form”。程序将弹出一 个窗口如下: 可以看到在窗口左上方有一个“templatesforms”的菜单,下面有四个可供选择的模板。 第一个和第二个都是对话框,区别在于对话框中按钮的位置不同。第三个是主窗口,第四 个是窗口部件。本例中我们需要选择第四个选项(Widget)。 现在你应该可以看到 Qt Designer 为你生成了一个窗口,标题栏是“Untitled”(也许你觉得第一个模板更加适合我们的例子, 不过,在这里,我们将手动添加“OK”和“Cancel”这两个按钮)。 我们按照上面讲过的顺序来设计这个窗口。首先需要生成子窗口部件并将它们放置 在工作台上。在 Qt Designer 工作界面的左侧,我们可以看到很多程序设计经常用到的窗口 部件。如果你需要它们中的那一个,用鼠标把它拖到工作台上就可以了。我们在菜单“Display Widgets”中选择一个“Label”,在菜单“Input Widgets”中选择一个“Line Edit”,在菜单 “Spacers”中选择一个“Horizontal Spacer”(这个空白组件在最终形成的窗口中是不可见的, 在 Qt Designer 中,空白组件的样子就像是一个蓝色的弹簧),在菜单“Buttons”中选择两个 “Push Button”。按照下图的位置,将它们摆放起来。 你可以看到,我们的工作界面显的太大了一些,可以用鼠标拉住边框让它改变大小, 直到你满意为止。一个类似下图的组件是不是已经出现了?记住不要花费太多的时间来摆放 这些窗口部件的位置,只要大概类似就可以了,因为他们并不是不可调整的。Qt 的布局管 理器将会对他们的位置和大小自动进行一些优化。 现在我们已经创建了这些子窗口部件,并把他们放置在了合适的位置,接下来要做 的就是初始化他们。这需要设定这些子窗口的属性。在 Qt Designer 工作界面的右侧也同样 有一些窗口,这些就是属性窗口。 可以在这些窗口中找到所有部件需要设置的属性,并更改 它们,就可以达到我们的目的了。 1)、点击 TextLabel,确认它的“objectName”属性是“label”,然后将它的“text”属 性设置为“&Cell Location”。 2)、点击 line editor (窗口中的空白编辑框),确认它的“objectName”属性是“lineEdit”。 3)、点击第一个按钮(左侧),将其“objectName”属性设置为“OKButton”,“enable” 属性设置为“false”,“text”属性设置为“OK”,“default”属性设置为“true”。 4)、点击第二个按钮(右侧),将其“objectName”属性设置为“cancelButton”,“text” 属性设置为“Cancel”。 5)、点击工作平台的背景,这样我们可以选择整个的界面。这也是一个窗口,也拥有 自己的属性。我们把它的“objectName”属性设置为“GoToCellDialog”,“windowtTitle”属 性设置为“Go to Cell”。 完成后的 Form 变成了下图的形式: 接下来我们给 Label 设置一个伙伴(buddy),在这个例子中, Label 的伙伴当然是后面 的字符编辑框 line editor。在 Qt Designer 的菜单中进行选择:Edit->Edit Buddies。这样我们 进入 Buddy 模式,可以设置子窗口的伙伴了。点击 Label,Label 将会变成红色的,同时出 现一条线,将这条线拖拽到后面的 line editor 上,然后松开。这时两个窗口都将变成红色的, 中间有一条红线相连。移动鼠标到别处并点击,窗口将变成蓝色的。这说明我们已经设置成 功了(如果设置错误,则可以用鼠标在连接窗口的线条上点击,这时相连的窗口又会变成红 色的,此时按 Delete 键就可以取消设置)。选择:Edit->Edit Widget,可以退出这个模式,回 到主菜单中。如下图所示: 接下来我们对工作台上的各个子窗口进行布局: 1)、 点击标签“Cell Location”,按住 Shift 键,再点击后面的字符编辑框“line editor”, 这样它们两个窗口被同时选中。选择菜单:Form->Lay Out Horizontally。这样这两个窗口将 被一个红色边框的矩形包围。 2)点击空白子窗口“Spacer”,按住 Shift 键,再点击后面的两个按钮,同时选定这三 个窗口,然后选择菜单:Form->Lay Out Horizontally。这样这三个窗口将被一个红色边框的 矩形包围。 3)、点击工作平台的背景,取消任何已经选择的组件,然后选择:Form->Lay Out Vertically。这样我们可以将第 1 步和第 2 步所生成的两个水平布局进行垂直布局。 4)、选择菜单:Form->Adjust Size。这样我们可以调整主窗口的大小。最后效果如下 图(图中的红线在程序最终生成的时候不会被显示): 然后我们对 Tab 的顺序进行设置。选择菜单:Edit->Edit Tab Order。一个带有数字的 蓝色矩形会显示在每一个窗口部件上(由于我们将 Label 和 line editor 设置为 buddy,这样 它们在指定 Tab 的时候被视为一个组件)。点击这些带数字的矩形可以调整到你想要的顺序 上,然后选择:Edit->Edit Widgets 离开这个模式。 现在我们的对话框的外形已经完成了。选择菜单:Form->Preview。这样你可以预览我 们设计的窗口。可以反复按下 Tab 键来验证顺序是否和我们设置的一致。点击顶部的关闭按 钮就可以关闭这个预览窗口。 所有的界面设计工作已经完成了,现在我们要做的就是保存下来。选择菜单: File->Save Form As:。建立一个名为“gotocell”的文件夹,将这个界面保存为名称为“gotocelldialog.ui” 的文件中,放置到新建的文件夹中。 下面我们试着显示这个对话框。在文件夹“gotocell”中建立一个文件 main.cpp。在 cpp 文件中编写代码如下: #include #include #include "ui_gotocelldialog.h" int main (int argc, char *argv []) { QApplication app (argc, argv); Ui::GoToCellDialog ui; QDialog *dialog = new QDialog; ui.setupUi (dialog); dialog->show (); return app. exec (); } 现在我们运行 qmake 工具来生成一个工程文件 (.pro)和一个 makefile (qmake –project; qmake gotocell.pro)。qmake 是一个足够聪明的工具,它可以侦测到当前文件夹中的用户界 面文件(在本例中就是我们刚才保存的 gotocelldialog.ui),并且自动生成合适的 makefile 规则来调用 uic(uic 就是 Qt 的用户界面编译器)。Uic 工具将把文件 gotocelldialog.ui 的内 容转换成 C++代码,写入自动生成的头文件“ui_gotocelldialog.h”中。 生成的头文件“ui_gotocelldialog.h”包括了对类 Ui::GoToCellDialog 的定义。这是一 个和 gotocelldialog.ui 文件内容相同的定义,只不过它是用 C++表示的。这个类声明了存储 各个子窗口和布局的成员变量,还包括一个 setupUi()的成员函数,用来初始化程序窗口。生 成的类就像下面所显示的一样: class Ui::GoToCellDialog { public: QLabel *label; QLineEdit *lineEdit; QSpacerItem *spacerItem; QPushButton *okButton; QPushButton *cancelButton; ... void setupUi (QWidget *widget) { ... } }; 这个自动生成的类并没有继承任何 Qt 的类。当我们在 main.cpp 中使用这个界面的时 候,我们创建一个 QDialog 并把它传递给函数 setupUi()。 现在可以编译并运行这个程序了。程序界面已经可以开始工作了,但是你会发现一些 问题——界面的功能并没有完全实现: 1)、按钮“OK”总是不可见的。 2)、按钮“Cancel”虽然可以显示,但它什么也不能做。 3)、字符编辑框接受任何字符,而不是像我们期望的那样只接受合法的数字。 显然我们应该通过编辑一些代码来使对话框函数正确地工作。最干净利落的方法是类 继承。我们创建一个新的类,这个类同时继承 QDialog(程序中创建的,被传递给函数 setupUi())和 Ui::GoToCellDialog,并完成这些未实现的功能(这也验证了一条名言:任何 软件的问题都可以通过添加一个间接的层来解决)。对于这样的一个类,我们的命名习惯是: 把 uic 生成的类去掉前缀“Ui::”作为我们的类名称。本例中,这个类叫 GoToCellDialog。 创建一个头文件 gotocelldialog.h,在里面编辑代码如下: #ifndef GOTOCELLDIALOG_H #define GOTOCELLDIALOG_H #include #include "ui_gotocelldialog.h" class GoToCellDialog: public QDialog, public Ui::GoToCellDialog { Q_OBJECT public: GoToCellDialog (QWidget *parent = 0); private slots: void on_lineEdit_textChanged (); }; #endif 有了头文件,我们还需要源文件。再创建一个 gotocelldialog.cpp,编辑代码如下: #include #include "gotocelldialog.h" GoToCellDialog::GoToCellDialog (QWidget *parent) : QDialog (parent) { setupUi (this); QRegExp regExp ("[A-Za-z] [1-9] [0-9] {0, 2}"); lineEdit->setValidator (new QRegExpValidator (regExp, this)); connect (okButton, SIGNAL (clicked ()), this, SLOT (accept ())); connect (cancelButton, SIGNAL (clicked ()), this, SLOT (reject ())); } void GoToCellDialog::on_lineEdit_textChanged () { okButton->setEnabled (lineEdit->hasAcceptableInput ()); } 在构造函数中,我们调用了 setupUi()来初始化工作平台。由于采用了多重继承,这使 得我们可以直接访问类 Ui::GoToCellDialog 的成员变量。在用户界面生成之后,函数 setupUi() 将会把任何遵循命名规则:on_objectName_signalName()而命名的槽和“objectName”中的 信号 signalName()连接起来。在这个例子中,这意味着函数 setupUi()将会建立如下的连接: connect (lineEdit, SIGNAL (textChanged (const QString &)), this, SLOT (on_lineEdit_textChanged ())); 同样的,在构造函数中,我们设置了一个验证器(validator)来限制输入的范围。Qt 有三个内置的验证器,他们分别是:QIntValidator,QDoubleValidator 和 QRegExpvalidator。 这里我们使用了一个 QRegExpValidator 验证器,其规则表达式为"[A-Za-z] [1-9] [0-9] {0, 2}"。 它表示:允许一个大写或者小写的字母,这个字母后面紧跟着一个取值范围为[1-9]的数字, 再紧跟位数取值范围为[0-2] (即不可超过 100)的数字,这个数字每一位的取值范围是[0-9]。 我们把一个 this 指针传递给验证器 QRegExpValidator 的构造函数,这样我们使它成为 对象 GoToCellDialog 的一个子对象。通过这样,我们就不必在后面花费心思考虑对于这个 QRegExpValidator 的删除——它会在它的父对象被删除时自动销毁。 Qt 的父子机制是在 QObject 中实现的。当我们从父对象中产生一个子对象时(可以是 一个 widget,一个 validator 或者任何形式),父对象就把这个对象加入到它的子对象链表中。 当父对象被删除时,它会遍历这个链表并销毁每一个子对象。这些子对象然后再继续销毁属 于它们的子对象。如此的循环,直到没有对象剩下为止。 这种机制极大地简化了程序的内存管理任务,减少了内存泄露的危险。当我们删除父 窗口时,子窗口不光从内存中消失,从屏幕上也会消失。 在构造函数的最后,我们将按钮 OK 和 QDialog 的槽 accept()相连;将按钮 Cancel 和 槽 reject()相连。这两个槽都会关闭窗口,但是 accept()将对话框的结果传给 QDialog::Accepted (实际上是整数 1);而 reject()则将对话框的结果传给 QDialog::Rejected (实际上是整数 0) 。 当我们使用这个对话框的时候,我们可以查看它的返回值来确认用户是否按下了按钮 OK; 程序运行是否正确。 槽 on_lineEdit_textChanged()的作用是:根据字符编辑框中的内容是否合法来决定按钮 OK 可见或不可见。函数 QLineEdit::hasAcceptableInput()使用了我们在构造函数中看到过的 验证器。 以上我们已经完成了对话框的所有工作。现在我们重写 main.cpp: #include #include "gotocelldialog.h" int main (int argc, char *argv []) { QApplication app (argc, argv); GoToCellDialog *dialog = new GoToCellDialog; dialog->show (); return app.exec (); } 重新编译并执行程序。我们的程序可以正常工作了。 使用 Qt Designer 的好处之一是把程序员从必须修改他们的代码来适应界面的改变这 个烦恼中解脱出来。如果你使用纯粹的代码来编写界面,改变界面设计将耗费大量的时间。 应用 Qt Designer 将不会有任何时间上的损失: uic 工具会根据界面的改变自动更新代码。对 话框用户界面被保存为 .ui 文件的格式(基于 XML 的文件格式), 通过派生 uic 工具生成的 类,这种普遍的泛函性得到了实现。 |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
3106 浏览 3 评论
1559 浏览 3 评论
4708 浏览 1 评论
2047 浏览 1 评论
3300 浏览 2 评论
540浏览 1评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-25 07:58 , Processed in 0.635053 second(s), Total 62, Slave 47 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号