目录
2.0 本章目标
2.1 编写 Hello World 程序
2.1.1 新建Qt Widgets 应用
2.1.2 文件说明与页面设计
2.2 程序的运行与发布
2.2.1 程序的运行
2.2.2 程序的发布
2.2.3 设置应用程序图标
2.3 helloworld程序源码与编译过程详解
2.3.1 纯代码编写程序与命令行编译
2.3.2 使用UI文件
2.3.3 自定义C++类
2.3.4 使用 Qt 设计师界面类
2.4 项目模式和项目文件介绍
2.4.1 项目模式
2.4.2 项目文件
这章将从一个Hello World程序讲起,先讲述一个Qt Widgets项目的创建、运行和发布的过程;然后再将整个项目分解,从单一的主函数文件,到使用图形界面.ui文件,再到自定义C++类和Qt图形界面类,一步一步分析解释每行代码,并从命令行编译运行,让读者清楚地看到Qt Creator创建、管理、编译和运行项目的内部实现。学完本章,读者就能够掌握Qt项目建立、编译、运行和发布的整个过程。
1.选择项目模板
选择”文件→新建文件或项目”菜单项(也可以直接按下Ctrl+N快捷键,或者单击欢迎模式中的New Project按钮),在选择模板页面选择Application中的Qt Widgets Application项,然后单击Choose按钮,如图2-1所示。
2.输入项目信息
在“项目介绍和位置”页面输入项目的名称为 helloworld,然后单击创建路径右边的“浏览”按钮来选择源码路径,比如这里是Z:\qt\lesson code\src。如果选中了这里的“设置默认的项目路径”,那么以后创建的项目会默认使用该目录,如图2-2所示。单击“下一步”进入下个页面。
注意:项目名和路径中都不能出现中文。
3.选择构建系统
这里选择qmake。
4.输入类信息
在“类信息”页面中创建一个自定义类。这里设定类名为HelloDialog,基类选择QDialog,表明该类继承自QDialog 类,使用这个类可以生成一个对话框界面。这时下面的头文件,源文件和界面文件都会自动生成,保持默认即可,如图2-4所示,然后单击“下一步”按钮。
5.设置项目管理
在这里可以看到这个项目的汇总信息,还可以使用版本控制系统,这个项目不会涉及,所以可以直接单击“下一步”按钮完成项目创建,如图2-4所示。
6.选择构建套件
这里选择 Desktop Qt 5.6.1 MinGW 32bit,下面默认为Debug 版本和Release版本分别设置了两个不同的目录,如图2-3所示,然后单击“下一步”按钮。
7.查看汇总
1.文件说明
项目建立完成后会直接进入编辑模式。界面的右边是编辑器,可以阅读和编辑代码。
如果觉得字体太小,则可以使用快捷键Ctrl+“+”(即同时按下Ctrl键和+号键)来放大字体,使用Ctrl+“-”(减号)来缩小字体,或者使用Ctrl键+鼠标滚轮,使用Ctrl +0(数字)可以使字体还原到默认大小。
再来看左边侧边栏,其中罗列了项目中的所有文件,如图2-8所示。现在打开项目目录(笔者这里是Z:\qt\lesson code\src\helloworld)可以看到,现在只有一个 helloworld文件夹,其中包括了6个文件,各个文件的说明如表2-1所列。这些文件的具体内容和用途会在后面的内容中详细讲解。
文件 说明 helloworld.pro 该文件是项目文件,其中包含了项目相关信息 helloworld.pro.user 该文件中包含了与用户有关的项目信息 hellodialog.h 该文件是新建的HelloDialog类的头文件 hellodialog.cpp 该文件是新建的HelloDialog类的源文件 main.cpp 该文件中包含了main()主函数 hellodialog.ui 该文件是设计师设计的页面对应的界面文件
2.页面设计
在Qt Creator的编辑模式下双击项目文件列表中界面文件分类下的 hellodialog.ui文件,这时便进入了设计模式,如图2-9所示。可以看到,设计模式由以下几部分构成:
Ⅰ.主设计区:主要用来设计界面以及编辑各个部件的属性。
Ⅱ.部件列表窗口(Widget Box):窗口分类罗列了各种常用的标准部件,可以使用鼠标将这些部件拖入主设计区中,放到主设计区中的界面上。
Ⅲ.对象查看器(Object Inspector):查看器列出了界面上所有部件的对象名称和父类,而且以树形结构显示了各个部件的所属关系。可以在这里单击对象来选中该部件。Ⅳ.属性编辑器(Property Editor):编辑器显示了各个部件的常用属性信息,可以更改部件的一些属性,如大小、位置等。这些属性按照从祖先继承的属性、从父类继承的属性和自己属性的顺序进行了分类。
Ⅴ.动作编辑器与信号槽编辑器:两个编辑器可以对相应的对象内容进行编辑。
Ⅵ.常用功能图标:
单击最上面侧边栏中的前4个图标可以进入相应的模式,分别是窗口部件编辑模式(这是默认模式)、信号/槽编辑模式,伙伴编辑模式和Tab顺序编辑模式。
后面的几个图标用来实现添加布局管理器以及调整大小等功能。
下面从部件列表中找到Label(标签)部件,然后按住鼠标左键将它拖到主设计区的界面上,再双击它进人编辑状态后输入“Hello World!你好Qt!”字符串。Qt Crea-tor的设计模式中有几个过滤器,就写着“Filter”的行输入框。例如,在部件列
表窗口过滤器中输入“Label”就快速定位到Label部件,不用自己再去查找。其他几个过滤器作用也是这样。还可以使用“工具→Form Editor”菜单项来实现预览设计效果,设置界面上的瓯格间距、在设计部件与其对应的源文件间进行切换等操作。这部分内容可以在帮助索引中通过Getting to Know Qt Designer关键字查看。
1.编译运行程序
Ctrl + R
弹出这个页面是因为刚才在设计时更改了页面,而hellodialog.ui文件被修改而未保存。可以选择构建之前总是先保存文件选项,这样以后再运行程序就也可以自动保存了。
2.查看构建项目生成的文件
再看一下项目目录中的文件可以发现,Z:\qt\lesson code\src目录下又多了一个build-helloworld-Desktop_Qt_5_6_1_MinGW_32bit-Debug文件夹,这是默认的构建目录。也就是说,Qt Creator将项目源文件和编译生成的文件进行了分类存放, helloworld文件夹中是项目源文件,这个文件夹存放的是编译后生成的文件。
进入该文件夹可以看到,这里有3个Makefile文件和一个ui_hellodialog.h文件,还有两个目录debug和 release,如下图所示。release文件夹是空的,进入 debug文件夹,有3个.o文件和一个.cpp文件,它们是编译时生成的中间文件,可以不必管它,而剩下的一个helloworld.exe 文件便是生成的可执行文件。
3.直接运行可执行文件
双击运行helloworld.exe,则弹出了下图所示的警告对话框,提示缺少Qt5Cored. dll文件,可以想到应用程序运行是需要dll动态链接库的,所以应该去Qt的安装目录下寻找该文件。在Qt安装目录的 bin目录(笔者这里的路径是R:\QT\QT\QT5.9.9\5.9.9\mingw53_32\bin)中找到缺失的dll文件复制到debug中就可以了。
其实还可以有其他办法:直接将Qt的bin目录路径加入到系统Path环境变量中去,这样程序运行时就可以自动找到bin目录中的dll文件了。具体做法是右击“计算机”,在弹出的级联菜单中选择“属性”,然后在弹出的系统属性对话框中选择“高级系统设置”项。如下图所示,单击“环境变量”按钮进入环境变量设置界面。在“系统变量”栏中找到Path变量,单击“编辑”弹出编辑系统变量对话框。在变量值的最后添加“R:\QT\QT\QT5.9.9\5.9.9\mingw53_32\bin,然后单击“确定”即可,如下图所示。
如果再次报错,请参照博客修改:
qt:无法定位程序输入点 __gxx_personality_v0 于动态链接库_mjx792的博客-CSDN博客https://blog.csdn.net/mjx792/article/details/120833256 我们再来运行,发现程序成功运行了。
1.如何在自己机器上运行
现在程序已经编译完成,那么怎样来发布它,让它在别人的计算机上也能运行呢?前面生成的debug版本程序依赖的 dll文件很大,那是因为debug版本程序中包含了调试信息,可以用来调试。而真正要发布程序时要使用release版本。下面回到QtCreator中对 helloworld程序进行release版本的编译。
在左下角的目标选择器(Target selector)中将构建目标设置为Release,如下图所示,然后单击运行图标。
编译完成后再看项目目录中Z:\qt\lesson code\src文件夹的release目录,其中已经生成了helloworld.exe文件。
可以看一下它的大小只有24 KB,而前面的debug版的helloworld.exe却有1.08 MB,相差很大。如果前面已经添加了Path系统环境变量,那么现在就可以直接双击运行该程序。
2.如何在别人机器上运行
如果要使Release版本的程序可以在别人的计算机上运行(当然,对方计算机也要是 Windows平台),还需要将几个dll文件与其一起发布。
可以在桌面上新建一个文件夹,重命名为“我的第一个Qt程序”,然后将release文件夹中的helloworld.exe复制过来,再去Qt安装目录的bin目录中将libgcc_s_dw2-1. dll、libstdc++-6.dll、 lib-winpthread-1.dll、Qt5Core.dlI、Qt5Gui.dll 和 Qt5Widgets.dll这6个文件复制过来。另外,还需要将R:\QT\QT\QT5.9.9\5.9.9\mingw53_32\plugins\platforms目录中的platforms文件夹复制过来(不要修改该文件夹名称),里面只需要保留qwindows.dll 文件即可。现在整个文件夹一共有19.3 MB,如果使用WinRAR等打包压缩软件对它进行压缩,就只有6 MB了,已经到达了可以接受的程度,这时就可以将压缩包发布出去了。
3.windeployqt工具
Qt提供了一个 windeployqt工具来自动创建可部署的文件夹。例如,生成的release版本可执行文件在Z:\qt\lesson code\src\build-helloworld-Desktop_Qt_5_9_9_MinGW_32bit-Release\release文件夹中,则只需要在开始菜单的Qt 5.9.9菜单中启动Qt 5.9.9 (MinGW 5.3.0 32-bit)命令行工具,然后输入下面命令即可:
步骤是先cd到exe文件下,然后再调用windeployqt + 可执行文件名就可以了。
用windeployqt工具会将所有可用的文件都复制过来,有些可能是现在并不需要的,所以建议一般情况下不要使用,只有在无法确定程序依赖的文件时再使用该工具。如果不想使用Qt 5.6 for Desktop命令行工具来运行该命令,而是用cmd命令行提示符,那么必须保证已经将Qt安装目录的bin目录路径添加到了系统PATH环境变量中。
若程序中使用了png 以外格式的图片,则发布程序时就要将Qt安装目录下的plugins目录中的imageformats文件夹复制到发布程序文件夹中,其中只要保留自己用到的文件格式的dll文件即可。例如用到了gif文件,那么只需要保留qgif.dll。如果程序中使用了其他的模块,比如数据库,那么就要将plugins目录中的sqldrivers文件夹复制过来,里面只须保留用到的数据库dll文件。
4.静态编译
到这里就已经完成了开发一个应用程序的最基本流程。下面再来看一个经常被提到的概念:静态编译。静态编译是相对于前面讲到的动态编译而言的。就像前面看到的一样,在Qt Creator默认的情况下,编译的程序要想发布就需要包含dll文件,这种编译方式被称为动态编译。
而静态编译就是将Qt的库进行重新编译,用静态编译的Qt库来链接程序,这样生成的目标文件就可以直接运行,而不再需要dll文件的支持。不过这样生成的exe文件也就很大了,有好几MB,而且静态编译缺乏灵活性,也不能部署插件。
从前面的介绍可以看到,其实发布程序时带几个dll文件并不是很复杂的事情,而且如果要同时发布多个应用程序,还可以共用dll文件,所以使用默认的方式就可以了。想了解更多Qt发布的知识和静态编译的方法,可以在Qt Creator帮助的索引方式下通过Deploying Qt Applications关键字查看,Windows平台发布程序对应的关键字是Qt for Windows-Deployment。
若程序发布时想使exe文件有一个漂亮的图标,则可以在 Qt Creator的帮助索引中查找Setting the Application Icon关键字,这里列出了在 Windows上设置应用程序图标的方法,步骤如下:
第一步,创建.ico文件。将ico图标文件复制到工程文件夹的helloworld目录中,重命名为“myico.ico”。完成后helloworld 文件夹中的内容如下图所示。第二步,修改项目文件。如下图2-15所示,在Qt Creator中的编辑模式双击hel-loworld.pro文件,在最后面添加下面一行代码:
RC_ICONS = myico.ico
第三步,运行程序。如下图所示,可以看到窗口左上角的图标已经更换了。然后查看一下release文件夹中的文件,可以看到,现在exe文件已经更换了新的图标,如下图所示:
现在只需要将这里的helloworld.exe复制到程序发布文件夹中,就可以得到一个完整而且漂亮的应用程序。对于整个流程而言,最后这步“设置应用程序图标”并不是必须的。这就是程序从创建到发布的整个过程。
1.创建一个程序运行
第一步,新建空项目。打开Qt Creator并新建项目,选择“其他项目”中的 Emptyqmake Project,如下图所示。
然后将项目命名为 helloworld并设置路径。完成后,双击helloworld. pro文件,添加一行代码:
greaterThan(QT_MAJOR_VERSION,4):QT += widgets
然后按下Ctrl+S保存该文件。这行代码的意思是,如果Qt主版本大于4(也就是说当前使用的是Qt 5或者更高版本),则需要添加 widgets模块。因为后面程序中使用的几个类都包含在 widgets模块中,所以这里需要添加这行代码。其实,直接使用“QT += widgets”也是可以的,但是为了保持与Qt 4的兼容性,建议使用这种方式。
第二步,往项目中添加main.cpp文件。在项目文件列表中的项目文件夹 helloworld 上右击,在弹出的级联菜单中选择“添加新文件”项,然后选择C++Source File,名称设置为main.cpp,路径就是默认的项目目录,后面的选项保持默认即可。第三步,编写源代码。向新建的main.cpp文件中添加如下代码:
#include
#include #include int main(int argc,char * argv[]) { QApplication a(argc,argv); QDialog w; QLabel lable(&w); lable.setText("hello QT!"); w.show(); return a.exec(); } 前3行是头文件包含。Qt中每一个类都有一个与其同名的头文件,因为后面用到了QApplication、QDialog 、QLabel这3个类,所以这里要包含这些类的定义。
第4行就是在C++中最常见到的main()函数,它有两个参数,用来接收命令行参数。
第6行新建了QApplication类对象,用于管理应用程序的资源,任何一个Qt Widgets程序都要有一个QApplication对象。因为Qt程序可以接收命令行参数,所以它需要argc和argv两个参数。
第7行新建了一个 QDialog对象,QDialog类用来实现一个对话框界面。
第8行新建了一个QLabel对象,并将QDialog对象作为参数,表明了对话框是它的父窗口,也就是说这个标签放在对话框窗口中。
第9行给标签设置要显示的字符。
第10行让对话框显示出来。
在默认情况下,新建的可视部件对象都是不可见的,要使用show()函数让它们显示出来。
第11行让QApplication对象进入事件循环,这样当Qt应用程序运行时便可以接收产生的事件,例如单击和键盘按下等事件,这一点可以参考一下第6章的相关内容。
第四步,编译运行。运行程序结果如下图所示。
按下Alt+4快捷键可以显示编译输出信息,如下图所示。再看运行的程序,发现窗口太小,下面继续更改代码。
第五步,更改main.cpp如下:
#include
#include #include int main(int argc,char * argv[]) { QApplication a(argc,argv); QDialog w; w.resize(400,300); QLabel lable(&w); lable.move(120,120); lable.setText(QObject::tr("Hello Qt")); w.show(); return a.exec(); } 如果想改变对话框的大小,则可以使用QDialog类中的函数来实现。
在第7行代码下面另起一行,输入“w.”(注意,w后面输入一个点“.”),这时会弹出QDialog类中所有成员的列表,可以使用键盘的向下方向键↓来浏览列表。根据字面意思,这里选定了resize()函数。这时按下Enter键,代码便自动补全,并且显示出了resize()函数的原型。
它有两个重载形式,可以用键盘方向键来查看另外的形式,这里的“int w,int h”应该就是宽和高了。所以写出了第8行代码,设置对话框宽为400,高为300(单位是像素)。还要说明的是,编写代码时所有的符号都要用输入法中的英文半角(中文字符串中的除外)。然后在第10行代码中设置了label在对话框中的位置,默认对话框的左上角是(0,0)点。
第11行添加的QObject::tr()函数可以实现多语言支持,建议程序中所有要显示到界面上的字符串都使用tr()函数括起来,这个在第9章国际化部分将会讲到。虽然使用这种方法可以很简单地实现中文显示,不过还是建议正规编写代码时全部使用英文,最后使用第9章讲到的国际化方式来实现中文显示。现在可以运行程序查看效果。
2.常用功能
下面介绍两个实用功能:第一个是代码自动补全功能(可以在帮助索引中通过Completing Code关键字查看)。在编辑器中敲入代码时可以发现,打完开头几个字母后就会出现相关的列表选项,这些选项都是以这些字母开头的。现在要说明的是,如果要输入一个很长的字符,比如 setWindowTitle,那么可以直接输入swt这3个字母(就是setWindowTitle中首字母加其中的大写字母)来快速定位它,然后按 Enter按键就可以完成输入。列表中各个图标都代表一种数据类型,如下图所示。也可以使用“Ctrl+空格键”来强制代码补全,注意,它可能与系统输入法的快捷键冲突,这时可以在“工具→选项→环境→键盘→TextEditor”中修改快捷键,或者修改系统输入法的快捷键。
3.在命令行编译程序
前面在Qt Creator中使用纯代码实现了2.1节中的helloworld程序。下面不使用Qt Creator,而是在其他的编辑器(如Windows的记事本)中编写源码,然后再到命令行去编译运行该程序,步骤如下:
第一步,新建工程目录。在桌面新建文件夹helloworld,然后在其中新建文本文档,将Qt Creator的 main.cpp文件中的所有内容复制过来,并将文件另存为main.cpp(保存时要将编码选择为UTF-8,否则中文可能显示乱码),如下图所示。
第二步,使用命令编译程序。打开开始菜单中Qt安装目录下的命令提示符程序Qt 5. 6 for Desktop(MinGW 4.9.232 bit),先转到当前目录。在输入 qmake -project 生成pro工程文件,这时可以看到helloworld目录中已经生成了helloworld.pro文件。下面用记事本打开该文件,再最后面一行加入代码:greaterThan(QT_MAJOR_VERSION,4):QT+=widgets
然后输人qmake命令来生成用于编译的Makefile文件。
这时, helloworld目录中出现了Makefile文件和debug目录和release目录,当然这两个目录现在是空的。最后,输入“mingw32 - make”命令来编译程序,编译完成后会在 release目录中出现helloworld.exe文件。
整个编译过程如上图所示,看一下编译输出的信息可以发现,其与前面在Qt Creator 中的编译信息是类似的,只是这里默认编译了release版本;如果想编译debug版本,只需要更改命令参数即可。
这里对Qt程序的编译过程做一个简单的补充。上面使用的qmake是Qt提供的一个编译工具,它可以生成与平台无关的.pro文件,然后利用该文件生成与平台相关的Makefile文件。Makefile文件中包含了要创建的目标文件或可执行文件,创建目标文件所依赖的文件和创建每个目标文件时需要运行的命令等信息。
最后使用 mingw32 -make工具来完成自动编译, mingw32 - make就是通过读入 Makefile文件的内容来执行编译工作的。使用mingw32 - make命令时会为每一个源文件生成一个对应的.o目标文件,最后将这些目标文件进行链接来生成最终的可执行文件。qmake.exe工具在Qt安装目录的 bin目录中
第三步,运行程序。在命令行接着输入cd release命令,跳转到release目录下,然后输入helloworld. exe,按下回车键,就会运行helloworld程序了。
这就是Qt程序编辑、编译和运行的整个过程,可以看到,Qt Creator是将工程目录管理、源代码编辑和程序编译运行等功能集合在了一起,这也就是 IDE(集成开发环境)的含义。
1.使用.ui界面文件
第一步,添加.ui文件。在前面项目2-2基础上进行更改,先按照2.3.1小节添加main.cpp 文件那样向工程中继续添加文件。在模板中选择Qt中的Qt Designer Form。
在选择界面模板时选择Dialog without Buttons项,如下图所示。单击"下一步”,将文件名称改为hellodialog.ui。
2.设计页面
生成好文件后便进入了设计模式,在界面上添加一个Label部件,并且更改其显示内容为“Hello World!你好Qt!”。然后在右侧属性栏的geometry属性中更改其坐标位置为“X:120,Y:120”。这样就与那行代码“label.move(120,120);”起到了相同的作用。
然后在右上角的类列表中选择QDialog类对象,并且在下面的属性中更改它的对象名objectName为 HelloDialog,如下图所示。
第三步,生成ui头文件。按下Ctrl+S快捷键保存修改,然后按下Ctrl+2快捷键回到编辑模式,那么就会看到.ui文件的内容了,它是一个 XML文件,里面是界面部件的相关信息。
使用Ctrl+ Shift+B快捷键或者左下角的图标来构建工程。然后到本地磁盘的项目目录的build-helloworld-Desktop_Qt_5_6_1_MinGW_32bit-Debug目录中就可以看到由.ui文件生成的ui_hellodialog.h头文件了。下面来看一下这个头文件中的具体内容。
/******************************************************************************** ** Form generated from reading UI file 'hellodialog.ui' ** ** Created by: Qt User Interface Compiler version 5.9.9 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ #ifndef UI_HELLODIALOG_H #define UI_HELLODIALOG_H #include
#include #include #include #include #include #include QT_BEGIN_NAMESPACE class Ui_HelloDialog { public: QLabel *label; void setupUi(QDialog *HelloDialog) { if (HelloDialog->objectName().isEmpty()) HelloDialog->setObjectName(QStringLiteral("HelloDialog")); HelloDialog->resize(400, 300); label = new QLabel(HelloDialog); label->setObjectName(QStringLiteral("label")); label->setGeometry(QRect(120, 120, 171, 51)); retranslateUi(HelloDialog); QMetaObject::connectSlotsByName(HelloDialog); } // setupUi void retranslateUi(QDialog *HelloDialog) { HelloDialog->setWindowTitle(QApplication::translate("HelloDialog", "Dialog", Q_NULLPTR)); label->setText(QApplication::translate("HelloDialog", "Hello World! \344\275\240\345\245\275 Qt\357\274\201", Q_NULLPTR)); } // retranslateUi }; namespace Ui { class HelloDialog: public Ui_HelloDialog {}; } // namespace Ui QT_END_NAMESPACE #endif // UI_HELLODIALOG_H 其中,第1~7行是注释信息。
第9、10、55行是预处理指令,能够防止对这个头文件的多重包含。
第12~18行包含了几个类的头文件。
第20、53行是Qt的命名空间开始和结束宏。
第22行定义了一个 Ui_HelloDialog 类该类名就是在前面更改的框类对象的名称前添加了“Ui_”字符,这是默认的名字。
第25行定义了一个QLabel类对象的指针,这个就是对话框窗口添加的 Label 部件。第27行setupUi()函数用来生成界面,因为当时选择模板时使用的是对话框,所以现在这个函数的参数是QDialog类型的,后面会看到这个函数的用法。
第29和30行设置了对话框的对象名称。
第31行设置了窗口的大小,与之前在2.3.1小节中使用代码来设置是一样的。
第32~34行在对话框上创建了标签对象,并设置了它的对象名称、大小和位置。
第36行调用了re-translateUi()函数,这个函数在第41~45行进行了定义,实现了对窗口里的字符串进行编码转换的功能。
第38行调用了QMetaObject类的connectSlotsByName()静态函数,使得窗口中的部件可以实现按对象名进行信号和槽的关联,如 void on_buttonl_clicked(),这个在第7章信号和槽部分还会讲到。
第49~51行定义了命名空间UI,其中定义了一个 HelloDialog类,继承自Ui_HelloDialog类。
可以看到,Qt中使用ui文件生成了相应的头文件,其中代码的作用与2.3.1小节中纯代码编写程序中代码的作用是相同的。使用Qt设计师可以直观地看到设计的界面,而且省去了编写界面代码的过程。这里要说明的是,使用Qt设计师设计界面和全部自己用代码生成界面效果是相同的。以后章节中主要的界面都会使用Qt设计师来实现,如果想自己用代码来实现,则可以参考它的ui头文件,查看具体的代码实现。
第四步,更改main.cpp文件。将main.cpp文件中的内容更改如下:#include "ui_hellodialog.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); QDialog w; Ui::HelloDialog ui; ui.setupUi(&w); w.show(); return a.exec(); }
第一行代码是头文件包含。ui_hellodialog.h中已经包含了其他类的定义,所以这里只需要包含这个文件就可以了。对于头文件的包含,使用“<>”时,系统会到默认目录(编译器及环境变量、项目文件所定义的头文件寻找目录,包括Qt安装的include目录,即 R:\Qt\Qt5.9. 0\5.6mingw49_32\include)查找要包含的文件,这是标准方式;
用双引号时,系统先到用户当前目录(即项目目录)中查找要包含的文件,找不到再按标准方式查找。因为ui_hellodialog.h文件在自己的项目目录中,所以使用了双引号包含。第6行代码使用命名空间Ui中的HelloDialog类定义了一个ui对象。第7行中使用了setupUi()函数,并将对话框类对象作为参数,这样就可以将设计好的界面应用到对象w所表示的对话框上了。
第五步,运行程序,则可以看到与以前相同的对话框窗口了。
2. 在命令行编译ui文件和程序
第一步,新建工程目录。在桌面目录中新建文件夹helloworld_2,然后将上面的项目文件夹helloworld目录下的 hellodialog.ui和main.cpp两个文件复制过来。
第二步,编译.ui文件。打开命令提示符程序Qt 5.6 for Desktop (MinGW 4.9.232 bit),然后输入“cd 桌面”命令进入 helloworld_2文件夹中。再使用uic编译工具,从ui文件生成头文件。具体命令是:uic -o ui_hellodialog.h hellodialog.ui
就像前面看到的那样,.ui文件生成的默认头文件的名称是“ui_”加.ui 文件的名称。这时在helloworld_2目录中已经生成了相应的头文件。
第三步,编译运行程序。输入如下命令:qmake -project
这时在 helloworld __2.pro文件中添加“QT+= widgets”,然后依次执行如下命令:
qmake mingw32 -make cd release helloworld_2.exe
这样就完成了整个编译运行过程。可以看到,.ui文件是使用uic编译工具来编译的,这里的Qt程序通过调用相应的头文件来使用ui界面文件。
该小节首先新建空工程并且建立自定义的一个C++类,然后再使用上一小节的.ui 文件。通过这一小节的操作,读者可以看到Qt Creator中的设计师界面类是如何生成的。
第一步,新建空的Qt项目 Empty qmake Project,项目名称为 helloworld。完成后打开helloworld.pro文件,添加如下代码并保存该文件:greaterThan(QT_MAJOR_VERSION,4):QT += widgets
第二步,添加文件。向项目中添加新文件,模板选择C++Class。类名ClassName为 HelloDialog,基类Base class选择自定义
,然后在下面手动填写为QDialog,其他保持默认,如下图所示。添加完成后再往项目中添加main.cpp文件。 第三步,编写源码。在 main.cpp中添加如下代码:
#include
#include "hellodialog.h" int main(int argc,char * argv[]) { QApplication a(argc,argv); HelloDialog w; w.show(); return a.exec(); } 第四步,添加ui文件。将上一小节建立的 hellodialog.ui文件复制到项目目录下,然后在Qt Creator项目文件列表中的项目文件夹上右击,在弹出的级联菜单中选择“添加现有文件”,然后在弹出的对话框中选择helloworld.ui文件,将其添加到项目中。
第五步,更改C++类文件。这次不在 main()函数中使用ui文件,而是在新建立的C++类中使用。先将头文件hellodialog.h中修改如下:
#ifndef HELLODIALOG_H #define HELLODIALOG_H #include
namespace Ui { class HelloDialog; } class HelloDialog : public QDialog { Q_OBJECT public: explicit HelloDialog(QWidget * parent = 0); ~HelloDialog(); private: Ui::HelloDialog * ui; }; #endif // HELLODIALOG_H 第1、2和22行是预处理指令,避免该头文件多重包含。
第6~8行定义了命名空间Ui,并在其中前置声明了HelloDialog类,这个类就是在ui_hellodialog.h文件中看到的那个类。因为它与新定义的类同名,所以使用了Ui命名空间。而前置声明是为了加快编译速度,也可以避免在一个头文件中随意包含其他头文件而产生错误。
因为这里只使用了该类对象的指针,如第19行定义了该类对象的指针,这并不需要该类的完整定义,所以可以使用前置声明。这样就不用在这里添加ui_hellodialog.h的头文件包含,而可以将其放到hellodialog. cpp文件中进行。
第10行是新定义的 HelloDialog类,继承自QDialog类。
第12行定义了Q_OBJECT宏,扩展了普通C++类的功能,比如下一章要讲的信号和槽功能,必须在类定义的最开始处定义这个宏。
第15行是显式构造函数,参数是用来指定父窗口的,默认是没有父窗口。
第16行是析构函数。
然后在 hellodialog.cpp文件中添加代码:
#include "hellodialog.h" #include "ui_hellodialog.h" HelloDialog::HelloDialog(QWidget * parents): QDialog(parents) { ui = new Ui::HelloDialog; ui->setupUI(this); } HelloDialog::~HelloDialog() { delete ui; }
第2行包含了ui头文件,因为hellodialog.h文件中只使用了前置声明,所以头文件在这里添加。
第6行创建Ui::HelloDialog 对象。
第7行设置setupUi()函数的参数为this,表示为现在这个类所代表的对话框创建界面。也可以将ui的创建代码放到构造函数首部,代码如下:
HelloDialog::HelloDialog(QWidget * parent): QDialog(parent), ui(new Ui :: HelloDialog) { ui -> setupUi(this); }
这样与前面的代码效果是相同的,而且是Qt Creator生成的默认格式,建议以后使用这种方式。现在已经写出了和2.1节中使用Qt Creator创建的 helloworld项目中相同的文件和代码。此时可以再次运行程序。需要说明的是,这里使用ui文件的方法是单继承,还有一种多继承的方法,就是将HelloDialog类同时继承自QDialog类和Ui:: HelloDialog类,这样在写程序时就可以直接使用界面上的部件而不用添加ui指针的定义了。不过,现在Qt Creator默认生成的文件都使用单继承方式,所以这里只讲述了这种方式。也可以使用QUiLoader来动态加载ui文件,不过这种方式并不常用,这里也就不再介绍。若想了解这些知识,则可以参考Qt帮助文档的 Using a De-signer UI File in Your Application文档。
再次新建空项目,名称仍为helloworld。完成后在项目文件中添加widgets模块调用代码,然后向该项目中添加新文件,模板选择Qt中的“Qt设计师界面类”。界面模板依然选择Dialog without Buttons 一项,类名为HelloDialog。完成后在设计模式往窗口上添加一个Label,更改显示文本为“HelloWorld!你好Qt!”。然后再往项目中添加 main.cpp文件,并更改其内容如下:
#include
#include "hellodialog.h" int main(int argc,char * argv[]) { QApplication a(argc,argv); HelloDialog w; w.show(); return a.exec(); } 现在可以运行程序。不过,还要说明一下,如果在建立这个项目时,没有关闭上一个项目,在Qt Creator的项目文件列表中应该有两个项目,可以在这个项目的项目文件夹上右击,在弹出的菜单中选择“运行”,则本次运行该项目。也可以选择第一项“设置为活动项目”,那么就可以按下运行按钮或者使用Ctrl+R快捷键来运行该程序了。
本小节的内容就是将上一小节的内容进行简化,因为Qt设计师界面类就是上一小节的C++类和ui文件的结合,它将这两个文件一起生成了,而不用再一个一个的添加。
到这里就把Qt Creator自动生成Qt Widgets项目进行了分解再综合,一步一步地讲解了整个项目的组成和构建过程,看到了项目中每个文件的作用以及它们之间的联系。可以看到,同一个应用可以有很多编写代码方式来实现,而 Qt Creator背后为开发者做了很多事情。不过,读者最好也学会自己建立空项目,然后依次往里面添加各个文件,这种方式更灵活。
按下快捷键 Ctrl+5,或者单击“项目”图标,都可以进入项目模式。如果没有打开任何工程,则项目模式是不可用的。项目模式分为构建和运行、编辑器、代码风格、依赖关系和Clang Static Analyzer这5个页面。如果当前打开了多个项目,那么最上面会分别列出这些项目,可以选择自己要设置的项目。
在构建和运行页面可以设置要构建的版本,如 Debug版或是Release版本。还可以设置所使用的Qt版本。这里有一个'Shadow build选项,就是所谓的“影子构建”,作用是将项目的源码和编译生成的文件分别存放,就像在2.2.1小节讲到的, helloworld项目经编译后会生成build-helloworld-Desktop_Qt_5_6_1_MinGW_32bit-Debug文件夹,里面放着编译生成的所有文件。将编译输出与源代码分别存放是个很好的习惯,尤其是在使用多个Qt版本进行编译时更是如此。Shadow build选项默认是选中的,如果想让源码和编译生成的文件放在一个目录下,比如前面在命令行编译时那样,那么也可以将这个选项去掉。“构建步骤”、“清除步骤”和“构建环境”等选项前面都已经提过相关内容了,如果对编译命令不是很熟悉,这里保持默认就可以了,不用修改。
在编辑器中可以设置默认的文件编码、制表符和缩进、鼠标和键盘的相关功能,这些都是默认的全局设置,一般不建议修改,当然也可以按照自己的习惯进行自定义设置;在代码风格设置页面可以自定义代码风格,还可以将代码风格文件导出或者导入,这里默认使用了Qt的代码风格;在依赖关系中,如果同时打开了多个项目,则可以设置它们之间的依赖关系;Qt Creator集成的Clang Static Analyzer可以用来发现C、C++和Objective-C程序中的问题,具体使用方法可以在帮助中索引Using ClangStatic Analyzer关键字查看。这些选项一般都不需要更改,这里不再过多介绍。
下面来看一下2.1节中建立的 helloworld项目的helloworld.pro文件的内容:
QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++11 # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp \ hellodialog.cpp HEADERS += \ hellodialog.h FORMS += \ hellodialog.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target RC_ICONS = myico.ico
第1行表明这个项目使用的模块。core模块包含了Qt 的核心功能,其他所有模块都依赖于这个模块;gui模块提供了窗口系统集成、事件处理、OpenGL和OpenGL ES集成、2D图形、基本图像、字体和文本等功能。当使用qmake工具来构建项目时, core模块和gui模块是被默认包含的,这也是为什么前面手动编写项目文件时不添加这两个模块也可以编译的原因。
其实,所谓的模块就是很多相关类的集合,读者可以在Qt帮助中查看Qt Core和Qt GUI关键字。
第3行添加了widgets模块,这个前面介绍过了。Qt Widgets模块中提供了经典的桌面用户界面的UI元素集合,简单来说,所有C++程序用户界面部件都在该模块中。
三个+=分别是工程中包含的源文件、头文件和界面文件。
最后一行行就是添加的应用程序图标。这些文件都使用了相对路径,因为都在项目目录中,所以只写了文件名。
这里还要提一下那个在项目文件夹中生成的. pro.user文件,它包含了本地的构建信息,包含Qt版本和构建目录等。可以用记事本或者写字板将这个文件打开查看其内容。使用Qt Creator打开一个.pro文件时会自动生成一个.pro.user文件。因为读者的系统环境都不太一样,Qt的安装与设置也不尽相同,所以如果要将自己的源码公开,一般不需要包含这个user文件。如果要打开别人的项目文件,但里面包含了user文件,则 Qt Creator 会弹出提示窗口,询问是否载入特定的环境设置,这时应该选择“否”,然后选择自己的Qt套件即可。