![Qt 4开发实践](https://wfqqreader-1252317822.image.myqcloud.com/cover/891/687891/b_687891.jpg)
2.3 Qt的开发步骤及实例
大体了解开发Qt程序的基本流程有助于Qt开发快速入门。下面以完成计算圆面积功能这一简单例子来介绍一下Qt开发程序的流程,其中涉及到Qt应用程序用户界面中的事件关联操作内容——信号和槽机制(Signal&Slot)。
本实例要实现的功能是:当用户输入一个圆的半径后,可以显示计算后的圆的面积值。运行效果如图2.4所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0045_0035.jpg?sign=1739037909-4vVV05Nv4JKhEy4A2OCqXjS7x3dUh69S-0-d08645951a60576d08b27b72fbe88628)
图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所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0046_0036.jpg?sign=1739037909-KJrzli3ptQfV53fhfBAgmnRXzerUZnTq-0-6859be599bcf6d756739ad197bcc7e7d)
图2.5 创建一个新工程
(2) 因为需要建立一个Gui项目,所以选择“Qt4 Gui Application”,单击“OK”按钮,进入下一步。
此时,编程者在创建新工程时,需要创建什么样的工程就选择相应的工程选项即可。如:“Empty Qt4 Project”选项是创建一个空的工程;“Qt4 Console Application”选项是创建一个基于控制台的工程;“Qt4 Gui Application”选项是创建可以设计GUI的工程,如图2.6所示。选择“OK”按钮,进入下一步。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0046_0037.jpg?sign=1739037909-Qh0FStwqlTUQiZuC2Pnlt7LVwhBMnuQb-0-f88f12be678fdf22ff7e5e2bb4f640fc)
图2.6 建立一个Gui项目
(3) 选择保存项目的路径以及定义自己项目的名字。注意,保存项目的路径中不能有中文字。项目命名没有大小写要求,依据个人习惯命名即可。这里将项目命名为Dialog,保存路径为D:\CH201,如图2.7所示。单击“Next”按钮进入下一步骤。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0046_0038.jpg?sign=1739037909-A6vt5AZjlFC1OO8KowpmT5b5q7bIDUTJ-0-0bd9a2b0c4bac050e203c136dccb38b9)
图2.7 保存项目
(4) 出现“Select required modules”界面。现在按照自己项目需要,添加一些功能模块,如图2.8所示。这里不需要这些功能,直接单击“Next”按钮进入下一步骤。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0047_0039.jpg?sign=1739037909-rPlIuvdHNbRCAzRVlPW6HTSeo38fBLA3-0-ba4538ff4722ac0431b329fe6dc4f849)
图2.8 选择功能模块
(5) 根据实际需要,选择一个“Base class(基类)”。这里选择QDialog对话框类作为基类,这时“Class name”、“Header file”、“Source file”以及“Form file”都出现默认的文件名。注意,这些文件名都可以根据具体需要进行相应的修改。选中“Generate form”复选框,表示需要用自带的界面设计器来设计界面,否则需要用代码来完成界面的设计,如图2.9所示。选择完之后单击“Next”按钮进入下一步骤。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0047_0040.jpg?sign=1739037909-Hst7W4uhSkv6MC3vWpFkssx5j86ew5S7-0-94f9fc0a55494c523841b41a931c8783)
图2.9 选择基类
(6) 单击“Finish”按钮完成创建,则相应的文件自动加载到文件列表中,如图2.10所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0048_0041.jpg?sign=1739037909-xBAYSDa03WamXCyMXu892PKsF0IESIId-0-ccce68480c25bacf9fe7140caad4fa91)
图2.10 简单文件列表
此时显示的是简单的文件列表。单击中间灰色一列工具栏中的过滤符号()后,弹出一个下拉列表,此时使两个项目都是被勾选选中状态(默认选项“Simplify tree”没选中,“ide generated files”处于选中状态),如图2.11(a)所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0048_0043.jpg?sign=1739037909-toBy4lqzE2MYtoMJNfKtDi48IzElzb3J-0-fb8d2d3f747cb053dd399dcb888212e6)
图2.11 选择文件列表显示形式
若单击其中“Simplify tree”项取消选中状态,此时文件列表中的文件自动分类显示,如图2.11(b)所示。
在图2.11中,各个文件包含在文件夹中,单击文件夹前面的“”图标可以显示该文件夹下的文件,如图2.12(a)所示。当单击“
”图标时,可以隐藏该文件夹下的文件。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0048_0046.jpg?sign=1739037909-1IH3gnM1A3RT44hbbzq7u2QZiOsuEeh7-0-b96ba0eaa74d5bd01dfb4031ecf19410)
图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所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0049_0047.jpg?sign=1739037909-hQ3dFzUwHO3oEQzWCboRN8LbzKsAqnBp-0-265478a3b18c1c07d6989a0ab09209fe)
图2.13 Display Widgets容器栏
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0049_0048.jpg?sign=1739037909-YOCWwhLK1yBevBdDQVF0oiC6W3W2Rd45-0-c49eb73fc0d50a6d44807b006a8e305d)
图2.14 Input Widgets容器栏
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0049_0049.jpg?sign=1739037909-Eyz9JbD7kMZvMbiaUBe8livHg4A24RT7-0-68e8368f737385e2a0b420db9b895851)
图2.15 Buttons容器栏
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0049_0050.jpg?sign=1739037909-hgcHjeTpxoZRwIFeG6lkRONTH9eSVV0s-0-dd8dcc9579ffefe1a24c4a26de5ebfde)
图2.16 初步布局
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0049_0051.jpg?sign=1739037909-jXWXo0ktOhGwkbLRlb8tBEskXqNuZ7ZD-0-9896f58f4117e3c302e5d7c7a434710f)
图2.17 调整后的布局
下面将修改拖动到编辑框中的各控件的属性,如表2.1和图2.18所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0049_0052.jpg?sign=1739037909-fhHjtmlZUyKnUiImupArf4T4SLSK8DGq-0-7f315fdb1044e3e76c6dd6c401cc914c)
图2.18 对象监视器内容
表2.1 控件的属性
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0049_0054.jpg?sign=1739037909-hZ9WJt5pKrexztWmwr7cetICbpBw6dfR-0-ea25c33a6228d700d9b50486f6d27598)
其中,修改控件Text值的方法有两种:
● 直接双击控件本身即可修改;
● 在Qt Designer设计器中的属性栏中修改,例如修改表示半径的Label标签,如图2.19所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0049_0053.jpg?sign=1739037909-89KFaahZ03bOlhkuBp7cak4moFbBnUa1-0-edc6081abe2c9e4e09cd5804a15d7760)
图2.19 修改半径标签objectName及Text值
最后修改areaLabel_2的“frameShape”为Panel、“frameShadow”为Sunken,如图2.20所示。最终效果如图2.21所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0050_0055.jpg?sign=1739037909-91y3eZMeVCNFtBUTdZ9XmAv8BIB12nAr-0-be3c470ffb6f9e4ff7a22761b10e54b1)
图2.20 修改areaLabel_2属性
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0050_0056.jpg?sign=1739037909-5WUKnCDM8LHTvTYCtE9iBLV8t4xSlv9F-0-6bd6d46acdcc8937b4fa6ec31db54d3d)
图2.21 最终效果图
下面单击左下角的运行按钮()或者使用快捷键“Ctrl+R”来运行一下程序,这时提示是否保存,单击“Save All”按钮,如图2.22所示。运行结果如图2.4所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0050_0058.jpg?sign=1739037909-imoK435jZu3rBfPsTfHiItnNYSqRN0W6-0-55af98231d45a4a78c2daadca3be8c43)
图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所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0051_0059.jpg?sign=1739037909-O2NB3DapFXsknT7vkMyDVzSvYsdO6pHB-0-ebca67cb4cabe2c764ce0febf996323e)
图2.23 选择Go to slot...
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0051_0060.jpg?sign=1739037909-MzJb0oD6nCO0XvztwA3Yva05TOHYV9nE-0-4b0e0dad54cd34e19497fb06b49b0fcd)
图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所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0052_0061.jpg?sign=1739037909-I07hQu5wp21mmEPEYwk4eBtiF5ds16oH-0-6d4a27017071a8ab5a397b8a4b29e244)
图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所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0054_0063.jpg?sign=1739037909-PNxCcUkHv1gGRAr0oIKqEPLTfo2pg79t-0-df7f2fd387a42bc9a8b51abc5e909f24)
图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所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0054_0064.jpg?sign=1739037909-0AZ0cfBXhoY8UQl9zuAFW56GEUm4Wo38-0-86939ec5ff94e3b19c82eacd9c884017)
图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所示。
![](https://epubservercos.yuewen.com/2B733A/3590505703558801/epubprivate/OEBPS/Images/figure_0055_0065.jpg?sign=1739037909-9sVr496kCzbtaGla9TRcix5dFSLszYhO-0-4166f09052fbd2708d01e9df2743088f)
图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开发步骤已经介绍完毕,在以后章节的例子中就不再如此详细介绍了。