2.3 Qt的开发步骤及实例
大体了解开发Qt程序的基本流程有助于Qt开发快速入门。下面以完成计算圆面积功能这一简单例子来介绍一下Qt开发程序的流程,其中涉及到Qt应用程序用户界面中的事件关联操作内容——信号和槽机制(Signal&Slot)。
本实例要实现的功能是:当用户输入一个圆的半径后,可以显示计算后的圆的面积值。运行效果如图2.4所示。
图2.4 计算圆面积实例
Qt中开发应用程序既可以采用设计器Qt Designer方法,也可以采用编写代码方法。下面首先采用Qt设计器Qt Designer进行GUI应用程序开发,使读者对Qt开发程序的流程有一个初步的认识。然后再用编写代码的形式详细介绍Qt程序开发步骤。
2.3.1 设计器Qt Designer实现
用设计器Qt Designer实现计算圆面积,完成图2.4所示的功能,见代码CH201。步骤是:首先进行界面设计,然后编写相应的计算圆面积代码。
1.界面设计
步骤如下:
(1) 单击运行Qt Creator,进入欢迎界面如图2.1所示。单击“File”→“New File or Project...”,创建一个新的工程,如图2.5所示。
图2.5 创建一个新工程
(2) 因为需要建立一个Gui项目,所以选择“Qt4 Gui Application”,单击“OK”按钮,进入下一步。
此时,编程者在创建新工程时,需要创建什么样的工程就选择相应的工程选项即可。如:“Empty Qt4 Project”选项是创建一个空的工程;“Qt4 Console Application”选项是创建一个基于控制台的工程;“Qt4 Gui Application”选项是创建可以设计GUI的工程,如图2.6所示。选择“OK”按钮,进入下一步。
图2.6 建立一个Gui项目
(3) 选择保存项目的路径以及定义自己项目的名字。注意,保存项目的路径中不能有中文字。项目命名没有大小写要求,依据个人习惯命名即可。这里将项目命名为Dialog,保存路径为D:\CH201,如图2.7所示。单击“Next”按钮进入下一步骤。
图2.7 保存项目
(4) 出现“Select required modules”界面。现在按照自己项目需要,添加一些功能模块,如图2.8所示。这里不需要这些功能,直接单击“Next”按钮进入下一步骤。
图2.8 选择功能模块
(5) 根据实际需要,选择一个“Base class(基类)”。这里选择QDialog对话框类作为基类,这时“Class name”、“Header file”、“Source file”以及“Form file”都出现默认的文件名。注意,这些文件名都可以根据具体需要进行相应的修改。选中“Generate form”复选框,表示需要用自带的界面设计器来设计界面,否则需要用代码来完成界面的设计,如图2.9所示。选择完之后单击“Next”按钮进入下一步骤。
图2.9 选择基类
(6) 单击“Finish”按钮完成创建,则相应的文件自动加载到文件列表中,如图2.10所示。
图2.10 简单文件列表
此时显示的是简单的文件列表。单击中间灰色一列工具栏中的过滤符号()后,弹出一个下拉列表,此时使两个项目都是被勾选选中状态(默认选项“Simplify tree”没选中,“ide generated files”处于选中状态),如图2.11(a)所示。
图2.11 选择文件列表显示形式
若单击其中“Simplify tree”项取消选中状态,此时文件列表中的文件自动分类显示,如图2.11(b)所示。
在图2.11中,各个文件包含在文件夹中,单击文件夹前面的“”图标可以显示该文件夹下的文件,如图2.12(a)所示。当单击“”图标时,可以隐藏该文件夹下的文件。
图2.12 展开文件列表
若单击“Hide generated files”选项取消其选中状态,此时在文件列表中显示自动生成dialog.ui的头文件ui_dialog.h,如图2.12(b)所示。注意,在dialog.ui内添加控件并保存后才自动生成头文件ui_dialog.h。
(7) 双击dialog.ui,进入界面设计器Qt Designer编辑状态开始进行设计器(Qt Designer)编程。
拖动控件容器栏的滑动条,在最后Display Widgets容器栏(如图2.13所示)中找到Label标签控件,拖动3个此控件到中间的编辑框中;同样,在Input Widgets容器栏(如图2.14所示)中找到LineEdit标签控件,拖动1个此控件到中间的编辑框中,用来输入半径值;在Buttons容器栏(如图2.15所示)中找到Push Button标签控件,拖动1个此控件到中间的编辑框中,用来提交响应单击事件。调整各控件的位置,最后的初步布局如图2.16所示。单击编辑框的空白处使编辑框处于被选中状态,拖动右下角的小方框,调整整个框架的大小,直至调整到适当大小为止,如图2.17所示。
图2.13 Display Widgets容器栏
图2.14 Input Widgets容器栏
图2.15 Buttons容器栏
图2.16 初步布局
图2.17 调整后的布局
下面将修改拖动到编辑框中的各控件的属性,如表2.1和图2.18所示。
图2.18 对象监视器内容
表2.1 控件的属性
其中,修改控件Text值的方法有两种:
● 直接双击控件本身即可修改;
● 在Qt Designer设计器中的属性栏中修改,例如修改表示半径的Label标签,如图2.19所示。
图2.19 修改半径标签objectName及Text值
最后修改areaLabel_2的“frameShape”为Panel、“frameShadow”为Sunken,如图2.20所示。最终效果如图2.21所示。
图2.20 修改areaLabel_2属性
图2.21 最终效果图
下面单击左下角的运行按钮()或者使用快捷键“Ctrl+R”来运行一下程序,这时提示是否保存,单击“Save All”按钮,如图2.22所示。运行结果如图2.4所示。
图2.22 保存界面
至此,程序的界面设计已经完成。
2.编写相应的计算圆面积代码
首先简单认识一下Qt编程环境。找到文件列表中自动添加的main.cpp文件,如图2.12(a)所示。每个工程都有一个执行的入口函数,此文件中的main()函数就是此工程的入口。下面详细介绍一下main()函数的相关内容:
#include <QtGui/QApplication> #include "dialog.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); Dialog w; w.show(); return a.exec(); }
其中:
● #include <QtGui/QApplication>:Application类的定义。在每一个使用Qt图形化应用程序中都必须使用一个QApplication对象。QApplication管理了各种各样的图形化应用程序的广泛资源、基本设置、控制流以及事件处理等。
● #include "dialog.h":包含了程序中要完成功能的Dialog类的定义,在Dialog类中封装完成所需要的功能。注意,使用哪个类时就必须将包含该类的头文件引用过来。例如,要用到一个按钮类时,则必须在此处添加一行代码:#include <QPushButton>,这表明包含了按钮(QPushButton)类的定义。以上包含的头文件还可以写成<qapplication.h>和<qpushbutton.h>的形式。
● int main(int argc, char *argv[]):是应用程序的入口,几乎在使用Qt的所有情况下, main()函数只需要在把控制转交给Qt库之前执行初始化,然后Qt库通过事件来向程序告知用户的行为。所有Qt程序中都必须有且只有一个main()函数。有两个参数argc和argv, argc是命令行变量的数量,argv是命令行变量的数组。
● QApplication a(argc, argv):a是这个程序的QApplication对象。在任何Qt的窗口系统部件被使用之前创建QApplication对象是必须的。它在这里被创建并且处理这些命令行变量。所有被Qt识别的命令行参数都会从argv中被移去(并且argc也因此而减少)。
● Dialog w:创建一个对话框对象,在该类中完成各种功能。
● w.show():当创建一个窗口部件的时候,默认它是不可见的,必须调用show()函数来使它变为可见。
● return a.exec():程序进入消息循环,等待可能输入进行响应。这里就是main()把控制权转交给Qt,Qt完成事件处理工作,当应用程序退出的时候exec()的值就会返回。在exec()中,Qt接受并处理用户和系统的事件并且把它们传递给适当的窗口部件。
现在,有两种方式可以完成计算圆面积功能:一种是通过触发按钮事件完成(方式1),另一种是通过触发输入编辑框事件完成(方式2)。
方式1:在LineEdit文本框内输入半径值,然后单击“计算”按钮,则在areaLabel_2中显示对应的圆面积。编写代码步骤如下:
(1) 右击“计算”按钮,选择“Go to slot...”,如图2.23所示。在弹出的对话框中选择clicked()信号,如图2.24所示。
图2.23 选择Go to slot...
图2.24 选择QPushButton的signal
(2) 进入dialog.cpp文件中按钮单击事件的槽函数:on_countBtn_clicked()。信号与槽连接的具体说明参照后面的知识点连接部分。在此函数中添加如下代码:
void Dialog:: on_countBtn_clicked() { bool ok; QString tempStr; QString valueStr=ui->radiusLineEdit->text(); int valueInt=valueStr.toInt(&ok); double area=valueInt*valueInt*PI;//计算圆面积 ui->areaLabel_2->setText(tempStr.setNum(area)); }
(3) 在此文件开始处添加以下语句:
const static double PI=3.1416;
定义全局变量PI。
运行程序,在LineEdit内输入半径值,单击“计算”按钮后,显示圆面积,完成计算圆面积功能。
方式2:在LineEdit内输入半径值,不需要单击按钮触发单击事件,直接就在areaLabel_2中显示圆面积。编写代码步骤如下:
(1) 在“Line Edit”编辑框上单击鼠标右键,在弹出的菜单中选择“Go to slot...”菜单项,在弹出的对话框中选择“textChanged(QString)”信号,如图2.25所示。
图2.25 选择QLineEdit的signal
(2) 单击“OK”按钮,进入dialog.cpp文件中的文本编辑框,改变值内容事件的槽函数:on_radiusLineEdit_textChanged(QString )。在此函数中添加如下代码:
void Dialog::on_radiusLineEdit_textChanged(QString ) { bool ok; QString tempStr; QString valueStr=ui->radiusLineEdit->text(); int valueInt=valueStr.toInt(&ok); double area=valueInt*valueInt*PI;//计算圆面积 ui->areaLabel_2->setText(tempStr.setNum(area)); }
运行此程序,在Line Edit中输入半径值后,直接在areaLabel_2中显示圆的面积值,完成计算圆面积的功能。
2.3.2 编写代码实现
下面用编写代码的方法来实现计算圆面积的功能,见代码CH202。具体步骤如下:
(1) 首先创建一个新工程。创建过程和2.3.1中的第(1)步骤~第(6)步骤相同,只是在第(3)步骤中,项目命名为Dialog且保存路径为D:\CH202,在第(5)步骤中,取消“Generate form”的选中复选框状态。
(2) 在上述工程的dialog.h中添加如下加黑代码:
class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); private: QLabel *label1,*label2; QLineEdit *lineEdit; QPushButton *button; };
此时要在文件最开始加入头文件:
#include <QLabel> #include <QLineEdit> #include <QPushButton>
其中: Q_OBJECT宏的作用是启动 Qt元对象系统的一些特性(比如支持信号和槽等),它必须放置到类定义的私有区。
注意:在文件中用到哪个类时,需要此文件开始部分引用包含此类的头文件。
(3) 在dialog.cpp中添加如下代码:
Dialog::Dialog(QWidget *parent) { : QDialog(parent) label1=new QLabel(this); label1->setText(tr("请输入圆的半径:")); lineEdit=new QLineEdit(this); label2=new QLabel(this); button=new QPushButton(this); button->setText(tr("显示对应圆的面积")); QGridLayout *mainLayout=new QGridLayout(this); mainLayout->addWidget(label1,0,0); mainLayout->addWidget(lineEdit,0,1); mainLayout->addWidget(label2,1,0); mainLayout->addWidget(button,1,1); //setLayout(mainLayout); }
其中:QGridLayout *mainLayout=new QGridLayout(this):用于布局管理器,将所有控件的位置固定,具体布局管理器的使用方法参照后面第4章的内容。
(4) 在此文件一开始添加头文件:
#include <QGridLayout>
此时运行程序结果如图2.26所示。
图2.26 初步运行效果图
这时,会看到中文部分是乱码。为解决此问题在main.cpp中添加如下加黑代码:
int main(int argc, char *argv[]) { QApplication a(argc, argv); QTextCodec::setCodecForTr(QTextCodec::codecForLocale()); Dialog w; w.show(); return a.exec(); }
其中:类QTextCodec封装定义了显示文本(例如,“请输入圆的半径:”)字符集的转换功能。
添加头文件:
#include <QTextCodec>
再次运行程序,结果如图2.27所示。
图2.27 修改后运行效果图
以上代码完成了界面设计,下面同样以两种触发不同控件事件的方式来完成计算圆面积的功能。
方式1:在LineEdit文本框内输入所需圆的半径值,单击“显示对应圆的面积”后,在label2中显示相对应的圆的面积值。
(1) 打开dialog.h文件,在类构造函数声明后添加如下代码:
class Dialog : public QDialog { ... ... QPushButton *button; private slots: void showArea(); };
(2) 打开dialog.cpp文件,在构造函数中添加如下加黑代码:
Dialog::Dialog(QWidget *parent) : QDialog(parent) { ... ... mainLayout->addWidget(button,1,1); connect(button,SIGNAL(clicked()),this,SLOT(showArea())); }
(3) 最后在showArea()中实现显示圆面积功能,代码如下:
void Dialog::showArea() { bool ok; QString tempStr; QString valueStr=lineEdit->text(); int valueInt=valueStr.toInt(&ok); double area=valueInt*valueInt*PI; label2->setText(tempStr.setNum(area)); }
(4) 在此文件开始处添加全局变量:
const static double PI=3.1416;
(5) 在LineEdit中输入圆半径值,单击“pushbutton”后,在label2中显示对应的圆面积值,如图2.28所示。
图2.28 最终运行效果图
方式2:在LineEdit文本框中输入所需圆的半径值后,不必单击按钮,直接在label2中显示圆的面积值。操作步骤和方式1相同,只是在上述第(2)步骤当中,添加的代码修改为如下加黑代码:
Dialog::Dialog(QWidget *parent) : QDialog(parent) { ... ... mainLayout->addWidget(button,1,1); connect(lineEdit,SIGNAL(textChanged(QString)),this,SLOT(showArea())); }
重新运行程序,在LineEdit文本框中输入圆半径值后,不必单击按钮,直接在label2中显示对应的圆面积值。
基本的Qt开发步骤已经介绍完毕,在以后章节的例子中就不再如此详细介绍了。