代码拉取完成,页面将自动刷新
同步操作将从 qtguide/qtguide 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<title>ch02-04</title>
<link href="css/style.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="thumbnailviewer.css" type="text/css">
<script src="thumbnailviewer.js" type="text/javascript">
/***********************************************
* Image Thumbnail Viewer Script- © Dynamic Drive (www.dynamicdrive.com)
* This notice must stay intact for legal use.
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/
</script> </head>
<body>
<div class="os1">2.4 Hello Creator</div>
<br>
上节介绍了 Qt 图形程序的大致生成过程,本节开始使用集成开发环境 Qt Creator,在 Qt Creator 诞生之前, Qt 程序可以通过
qmake 命令行编译或者像上一节手动输入 g++ 命令编译,在 Linux 平台还有 KDevelop 这类 KDE 桌面程序开发环境(一般用
cmake 生成脚本)。在 Qt 被诺基亚收购之前,Qt 官方一直没有有自己的集成开发环境,诺基亚收购之后,力推了 Qt 自己的集成开发环境,就是 Qt
Creator,这为 Qt 开发带来很大的方便。<br>
如今 Qt Creator 功能十分强大了,包含项目模板生成、代码编辑、UI 设计、QML
界面编辑、调试程序、上下文帮助等丰富功能,而且支持手机平板设备、嵌入式设备等程序的开发调试。 本节通过一个简单例子展示 Qt Creator
的代码编辑和 UI 编辑功能。Qt 程序调试和 Qt 帮助系统在后续章节讲解。 <br>
<br>
<div class="os2">2.4.1 Qt Creator 界面概览</div>
<br>
从开始菜单打开 QtCreator 集成开发环境,启动之后看到类似下面的界面:<br>
<center><img src="images/ch02/ch02-04-01.png" alt="qtcreator" width="800"> </center>
QtCreator 里面最上方的是菜单栏,最左边的是一排功能按钮。左边按钮上半部分是 QtCreator
工作模式选择,共有七种工作模式:欢迎、编辑(编写代码)、设计(GUI可视化编辑)、Debug(调试程序)、项目(项目参数配置)、分析(程序执行效率分析)、帮助。
左边按钮下面四个是构建调试区,由上到下依次是Qt套件选择、运行、调试运行和构建。左边的设计按钮、项目按钮和构建调试区只有在打开或新建了项目之后才会变得可
用。<br>
<br>
QtCreator 下方的是定位工具和输出面板,在编写项目代码和运行、调试程序时会使用到。输出面板包括七个:问题(项目构建时的问题)、Search
Results(搜索项目文件内容)、应用程序输出(运行和调试信息显示)、编译输出(编译、链接命令及其输出信息)、QML/JS Console(QML
命令窗口)、概要信息(项目信息摘要)、Version Control(版本控制系统)。<br>
<br>
QtCreator 中间的区域是所选择的工作模式界面,默认是欢迎模式。欢迎模式有三个子功能,第一个 Project
是项目显示,包括之前的会话和项目记录。项目记录比较好理解,而会话涵盖内容比较广,一个会话可以是多个项目的列表,并含有它们的配置以及上次编辑位置记录、调试
断点等等。会话记录 的上方是新建项目的快捷按钮,项目记录的上方是打开项目的快捷按钮。欢迎模式另外两个子功能是浏览 Qt
库自带的示例和教程,感兴趣的读者可以自行打开看看。<br>
<br>
<div class="os2">2.4.2 新建项目</div>
<br>
接下来我们新建一个 HelloCreator 项目,看看 QtCreator 集成开发环境新建的窗体项目。打开 QtCreator 文件菜单,点击“新建
文件或项目”(快捷键 Ctrl+N),或者直接在欢迎模式点击快捷按钮“New Project”,都可以打开如下所示的新建项目对话框:<br>
<center><img src="images/ch02/ch02-04-02.png" alt="newproject" width="800"></center>
新建项目对话框里有五类项目模板:<br>
<ul>
<li>Application:Qt 应用程序,包括普通窗体程序和 QtQuick 程序。</li>
<li>Library:可以创建动态库、静态库以及 QtQuick 扩展插件、QtCreator 自身插件。</li>
<li>其他项目:可以创建单元测试项目、Qt4 设计师自定义控件、子目录项目等。</li>
<li>非 Qt 项目:可以创建纯 C 或 纯 C++ 项目。</li>
<li>导入项目:从版本控制系统管理的软件项目导入旧的项目。</li>
</ul>
本教程常用的只有第一类 Application。在 Qt 应用程序里有四个子模板:<br>
<ul>
<li>Qt Widgets Application:普通窗体模板,传统基于部件的窗体界面程序。</li>
<li>Qt Quick Application:使用 QtQuick 设计界面的应用程序,编译得到二进制可执行程序。</li>
<li>Qt 控制台应用:因为 Qt 主要用于图形界面设计,这个控制台项目模板基本不用的。</li>
<li>Qt Quick UI:使用 QtQuick 设计的界面文件 *.qml ,项目不需要编译,而是使用 qmlscene 工具预览界面。</li>
</ul>
本教程使用第一个子模板 Qt Widgets Application,开发普通的 Qt
窗体应用程序。选择该项目模板,点击对话框下方的“Choose...”按钮,进入 Qt Widgets Application 项目新建的向导界面:<br>
<center><img src="images/ch02/ch02-04-03.png" alt="widgetsapplication" width="800"></center>
将项目名称设置为 hellocreator ,创建路径设置为 D:\QtProjects\ch02,点击“下一步”,进入“Kit
Selection”界面:<br>
<center><img src="images/ch02/ch02-04-04.png" alt="kitselection" width="800"></center>
这一步是为 hellocreator 设置 Qt 套件(Qt Kits),默认只有第一个“Desktop Qt 5.4.0 MinGW
32bit”,如果安装配置了多个 Qt 套件,就可以都选上。Qt 套件是指 Qt 程序从编译链接到运行环境的全部工具和 Qt 类库的集合,对于
MinGW 版本 Qt 程序生成和调试,至少需要 MinGW 中的编译器 g++(自动调用链接器)、g++ 配套的基础库、调试器 gdb 还有使用
MinGW 环境编译而成的 Qt 类库自身。默认情况下,在上面 Kit Selection 里选中全部套件,然后点击“下一步”,进入“类信息”设置界面:<br>
<center><img src="images/ch02/ch02-04-05.png" alt="classinfo" width="800"></center>
在类信息设置界面,最关键的是基类的选择,目前是三种基类:<br>
<ul>
<li>QMainWindow:基于主窗口类的程序,一般用于较为复杂的应用程序,除了中央客户区界面,还可以包括菜单栏、工具栏、状态栏以及多个可停靠的
工具对话框等等。</li>
<li>QWidget:最简单最基本的窗体程序,里面可以放置多个控件实现程序功能。</li>
<li>QDialog:基于对话框的程序,对话框一般用于弹窗,也可以用于主界面显示。对话框是从 QWidget
继承而来的,并丰富了一些功能,如模态显示和返回值等。</li>
</ul>
我们当然从最简单的学起,在基类里选择 QWidget ,类名和文件名会根据基类自动修改,不需要额外设置。点击“下一步”,进入“项目管理”界面:<br>
<center><img src="images/ch02/ch02-04-06.png" alt="manage" width="800"></center>
在项目管理界面可以设置作为子项目,以及加入版本控制系统管理。这两个功能暂时用不到,都用默认的 <None> ,然后点击 “完成”。<br>
<br>
项目创建完成之后,QtCreator 会直接进入代码编辑模式,可以看到类似下图界面:<br>
<center><img src="images/ch02/ch02-04-07.png" alt="editmode" width="800"></center>
编辑模式左边竖排的两个窗口叫做“边栏”,上面的默认是项目文件管理窗口,下面的是打开文件列表窗口。在 QtCreator
菜单“控件”-->“显示边栏
Alt+0”,可以控制边栏的显示和隐藏。边栏里的窗口数目可以增加,边栏子窗口标题栏(其实是工具条,长得像标题栏,姑且这么称呼)有一排小按钮,最右边的是关
闭按钮,倒数第二个是增加分栏按钮,可以添加多个边栏子 窗口。边栏子窗口标题栏第一个控件是组合框,可以选择该子窗口的功能视图类型,目前可以选择 8
个视图类型:<br>
<ul>
<li>项目:即项目文件管理视图,可以选择项目里的文件进行编辑,包括 pro 文件也可以手动编辑。</li>
<li>打开文档:当前已经打开的文件列表,文件名右边如果有 * 号,是该文件被修改了但尚未保存。</li>
<li>书签:右击代码编辑器行号位置,看到“切换书签”,可以给代码行添加书签,方便跳转到该位置。</li>
<li>文件系统:相当于系统里的文件资源管理器,可以查看项目文件夹在磁盘里的实际文件列表。</li>
<li>类视图:可以查看项目里包含的类及相应源代码文件里的成员函数、成员变量。</li>
<li>大纲:编辑器所显示的当前文件的大纲列表,如名字空间、类名、成员函数、成员变量等。</li>
<li>类型层次:当前项目包含的类及其基类、派生类列表。</li>
<li>Include Hierarchy:包含视图,显示当前项目里 *.h 、*.cpp 以及 Qt 类库头文件之间的包含关系。</li>
</ul>
可见 QtCreator 提供的功能视图是很丰富的,这些视图不需要死记硬背,只要知道大概有这些东西,以后需要的时候会调出来就行了。一般用头两个就差不多
了,当然也可以建立多个分栏,启用 其他功能视图。边栏介绍到这里,再看看右边的代码编辑器:<br>
<center><img src="images/ch02/ch02-04-08.png" alt="codeedit"></center>
代码编辑器大致可以分为三个部分,带有一堆控件的标题栏(其实是工具条)、行首区和编辑区。先看看标题栏的10个控件,这些东西不需要记,因为打开
QtCreator 的时候,这些东西都在那里,用鼠标指向这些控件几秒钟,会自动显示这些控件的工具提示信息,这里将它们罗列出来,方便读者以后查阅而已:<br>
<ul>
<li>①和②:导航按钮“返回”和“前进”,这与网页浏览器的前进和后退按钮类似,可以在之前浏览的多个代码文件或一个代码文件里多个位置之间快速切换。</li>
<li>③:标识当前显示的文件是只读还是可写,一般都是可写的。</li>
<li>④:文件类型图标,当前显示文件的类型,这个控件其实是一个菜单按钮,点击可以弹出丰富的文件处理功能菜单,感兴趣的读者可以点开看看。</li>
<li>⑤:打开的文件名,可以在多个打开的文件之间选择切换,与边栏的“打开文档”视图是对应的。</li>
<li>⑥:关闭当前显示的文档。</li>
<li>⑦:选择符号,可以在当前显示的文件里多个函数、类、成员变量等之前快速切换,与边栏“大纲”视图是对应的。</li>
<li>⑧:为当前显示的文件添加额外的C++预处理指令,一般用不着。</li>
<li>⑨:编辑区光标的行号和列号。</li>
<li>⑩:代码编辑区分栏,可以增加多个编辑器窗口,显示多个打开的文档或显示较大源码文件的多个位置。</li>
</ul>
行首区是浅灰色背景的部分,主要用来显示代码行号,以及调试断点标志和代码书签标志。右击行首区可以弹出右键菜单,菜单里可以切换书签、编辑书签以及设置或取消断
点。同一行是既可以打断点也可以设置书签的,二者不冲突,其实它们根本就没关系。单击行号前面的浅灰色空白区可以直接打断点,再次单击可以取消断点,另外也可以用
快捷键 F9 设置或取消断点。代码书签一般用右键菜单来设置,也可以用快捷键 Ctrl+M 设置或取消书签。<br>
<br>
编辑区是程序员最为常用的部分了,就是写代码用的。编辑区当然有语法高亮显示了,而且从编辑区的复制出来的内容是 HTML 语法的丰富文本格式,如果粘贴到
Word 之类的文字处理软件中,会直接显示彩色高亮代码,这是很实用的功能。<br>
对于现代集成开发环境常见的变量名、类名、名字空间、函数名、类对象成员变量、结构体成员变量等等名字补全功能,QtCreator
编辑器当然也能很好地支持。变量/函数调用追踪、变量/函数声明追踪、类名或变量名函数名自动改名等常见的辅助功能,也都是支持的(选择要改或要追踪的名字,右击,在右键
菜单里有一大堆功能,Refactor菜单项里面有自动改名)。QtCreator 的编辑模式就介绍这么多,接下来看看图形界面可视化设计。<br>
<br>
<div class="os2">2.4.3 UI 编辑</div>
<br>
在 QtCreator 编辑模式边栏上面的项目视图里,包含一个 hellocreator.pro
项目文件和头文件、源文件、界面文件三个虚拟目录。这三个虚拟目录是项目里对文件类型的归类显示,widget.h 和 main.cpp、widget.cpp
三个代码文件在后续小节讲解,本小节先设计图形界面。点开界面文件目录,可以看到 widget.ui :<br>
<center><img src="images/ch02/ch02-04-09.png" alt="projectview"></center>
双击 widget.ui 文件,QtCreator 会自动进入设计模式,可以对图形界面进行可视化编辑:<br>
<center><img src="images/ch02/ch02-04-10.png" alt="designmode" width="800"></center>
这个设计模式界面和上一节的 Qt 设计师是完全类似的,而且这就是将设计师的功能做成插件,集成到 QtCreator 了。
当然设计师变成插件之后,和原来的独立设计师程序有区别,现在插件设计师自己的菜单集成到 QtCreator 菜单工具-->Form Editor
级联菜单里。预览窗口需要点击菜单工具-->Form
Editor-->预览。还有一个重要的变化是窗体编辑区的右键菜单里,多了“转到槽...”,这个在讲过信号和槽一章之后会经常用到。<br>
与上一节类似的,拖一个 Label 标签控件到窗体编辑区里,然后同上一节设置标签控件的<span style="color: rgb(0, 0, 0); font-family: Simsun; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; display: inline !important; float: none;">
geometry 的四个子属性: X 为 10,Y 为 10,宽度为 200,高度为 40</span>。接着编辑标签控件的 text 属性为
<h1>Hello Creator!</h1> ,看到效果如下:<br>
<center><img src="images/ch02/ch02-04-11.png" alt="hellocreator" width="800"></center>
上一节使用了 Qt 样式表(Qt Style Sheets,通常缩写成 QSS)更改了标签控件的前景色和背景色,通过标签控件的
setStyleSheet 函数实现的。其实不仅可以用 C++ 代码设置样式表,独立的设计师程序或 QtCreator
的设计师插件还可以直接编辑标签控件的 styleSheet 属性实现可视化地编辑样式表。<br>
按如下操作示范:选择 label 控件,右边属性编辑窗口里,找到 styleSheet 属性,点击进入该属性的编辑框:<br>
<center><img src="images/ch02/ch02-04-12.png" alt="styleSheet" width="800"></center>
找到编辑框右边的 “...” 按钮,点开来,看到样式表编辑对话框:<br>
<center><img src="images/ch02/ch02-04-13.png" alt="styleSheetEdit"></center>
“编辑样式表”对话框上方是四个按钮,点击按钮会显示如上图中的菜单。“添加资源”是给控件添加前景图、背景图、边框图等。“添加渐变”和“添加颜色”功能类似,
可以为控件设置各种样式的渐变色。“添加颜色”是给控件添加前景色 color、背景色 background-color、边框色 border-color
等等。点击“添加字体”会弹出字体设置对话框,可以改变控件显示文字的字体、字号、粗体等效果。这里可以简单添加一个前景色 color 和 背景色
background-color ,两个颜色读者可以随意设置。重要的是学会设置样式表颜色,至于颜色本身不重要。添加好 color 和
background-color 之后,点击下方的“OK” 按钮,在编辑样式表对话框关闭之后就会查看效果,类似下图所示:<br>
<center><img src="images/ch02/ch02-04-14.png" alt="styleSheetEdit2"></center>
如果多次设置了前景色 color ,那么该对话框里会有多个 color
行,实际显示时按照最后一行的颜色显示,其他颜色设置也是类似的。如果要取消已设置的颜色,只需删除该对话框中间文本框里相应的文本行即可,比如删除上面的
background-color 一行(行尾是以 ; 结束),然后添加渐变背景色如彩虹色 Rainbow :<br>
<center><img src="images/ch02/ch02-04-15.png" alt="styleSheetEdit3"></center>
注意,要点击“OK”按钮关闭对话框之后,效果才会显示出来。上图是设置好之后,重新打开编辑样式表对话框,方便截图给读者看的。设置好前景色红色和背景色彩虹渐
变色之后,可以按快捷键 Alt+Shift+R 预览效果,这里就不截图了。快捷键 Ctrl+S 是保存编辑过的文件,编辑代码或设计 UI
时要注意保存文件。样式表的可视化编辑介绍到这,下一小节讲解代码。<br>
<br>
<div class="os2">2.4.4 代码讲解</div>
<br>
点击 QtCreator 左侧“编辑”,回到代码编辑模式,可以看到 widget.ui 的 XML 代码:<br>
<center><img src="images/ch02/ch02-04-16.png" alt="ui" width="800"></center>
ui 文件一般只在设计模式用设计师插件来编辑,不要手动修改 XML 代码(ui 文件里的 XML 代码就不讲解了)。里面遵守严格的 XML
语法格式,改错了就难以正确生成图形界面了,设计好界面之后保存了就可以关闭 ui 文件。如果希望继续编辑图形界面就点击上图中的“Switch
Mode”。下次希望修改 ui 文件的话,就在项目视图双击打开 ui 文件,会自动进入设计模式。<br>
<br>
现在来看编辑模式边栏的项目视图,点开头文件、源文件、界面文件三个虚拟目录,可以看到 widget.h 、main.cpp、widget.cpp
、widget.ui ,还有 hellocreator.pro
项目文件,这个项目必要的代码文件就这五个,项目视图里三个目录是虚拟的,但这五个文件都是真实的,就在
D:\QtProjects\ch02\hellocreator 文件夹里。<br>
<br>
首先来看看 widget.h :<br>
<div class="code"> <span style=" color:#000080;">#ifndef</span><span style=" color:#c0c0c0;">
</span>WIDGET_H
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#define</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">WIDGET_H</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QWidget></span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">namespace</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Widget</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">:</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">public</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QWidget</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">Q_OBJECT</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">public</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">explicit</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QWidget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>parent<span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">0</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">~</span><span style=" font-style:italic; color:#000000;">Widget</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Ui</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">Widget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">};</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#endif</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">WIDGET_H</span></pre>
</div>
开头定义的 WIDGET_H 宏是防止重复包含,保证头文件只会被包含一次。接下来是包含了基类头文件 <QWidget> 。<br>
然后看到下面的声明:<br>
<div class="code"> <span style=" color:#808000;">namespace</span><span style=" color:#c0c0c0;">
</span><span style=" color:#800080;">Ui</span><span style=" color:#c0c0c0;">
</span><span style=" color:#000000;">{</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
这句是前向声明,表示 Ui 名字空间里有一个叫 Widget 的类,Ui::Widget 类就是在生成项目时,用 uic 工具编译 widget.ui
得到的 ui_widget.h 里的辅助构建界面类的名字。使用前向声明配合后续定义的类成员指针(Ui::Widget
*ui),就可以方便地使用辅助构建界面类 Ui::Widget,而不需要在头文件里包含 ui_widget.h。<br>
接着是类定义:<br>
<div class="code"> <span style=" color:#808000;">class</span><span style=" color:#c0c0c0;">
</span><span style=" color:#800080;">Widget</span><span style=" color:#c0c0c0;">
</span><span style=" color:#000000;">:</span><span style=" color:#c0c0c0;">
</span><span style=" color:#808000;">public</span><span style=" color:#c0c0c0;">
</span><span style=" color:#800080;">QWidget</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">Q_OBJECT</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">public</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">explicit</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QWidget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>parent<span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">0</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">~</span><span style=" font-style:italic; color:#000000;">Widget</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Ui</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">Widget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">};</span></pre>
</div>
这几句定义了全局类 Widget ,和 Ui::Widget 有重名,但有名字空间前缀区别。在 Ui
名字空间里的是辅助构建界面的类。不带名字空间前缀的是全局类,从 QWidget 继承而来,这是真正的窗口类,类定义开头必须要有 Q_OBJECT
宏以支持元对象系统。类里面接下来是全局类 Widget 的构造函数和析构函数,都是 public 类型。explicit
关键字是强调必须显式构造该类对象,不使用隐式转换间接生成该类的对象。构造函数里的参数只有父类对象指针,默认的 0 (NULL)代表没有父窗口,也就是以操
作系统桌面为父窗口的意思。<br>
类定义里最后一行定义了 Ui::Widget 类的指针,这时还没有创建实际的辅助构建类的对象,指针目前没有初始化,只是起到占位的作用,以后才会给它赋值。<br>
<br>
接下来看看全局类 Widget 的实体代码文件 widget.cpp :<br>
<div class="code"> <span style=" color:#000080;">#include</span><span style=" color:#c0c0c0;">
</span><span style=" color:#008000;">"widget.h"</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"ui_widget.h"</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">Widget</span><span style=" color:#000000;">(</span><span
style=" color:#800080;">QWidget</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">*</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QWidget</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">new</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#000000;">::</span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">setupUi</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">::~</span><span
style=" font-style:italic; color:#000000;">Widget</span><span style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">delete</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
widget.cpp 不仅要包含 widget.h ,还要包含生成项目过程中出现的 ui_widget.h ,因为在 widget.cpp
文件里需要构造 Ui::Widget 类对象,并且调用该类对象的函数。widget.cpp 里只有两个函数,首先来看构造函数:<br>
<div class="code"> <span style=" color:#800080;">Widget</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">Widget</span><span style=" color:#000000;">(</span><span
style=" color:#800080;">QWidget</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">*</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">:</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QWidget</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">new</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#000000;">::</span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">setupUi</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
这个构造函数第一行是函数定义,第二行是使用 parent 变量初始化基类 QWidget 的对象,第三行是用 new 构建了一个 Ui::Widget
对象,并将该对象指针初始化了私有成员指针 ui 。现在 ui 指针就是指向一个实际的辅助构建类的对象。构造函数大括号的内部只有一句,就是调用 ui
所指对象的 setupUi 函数,setupUi 函数会为 this(就是全局类 Widget 的对象自己)构建图形界面。如果要使用窗口里的控件,需要以
ui-> 来调用子控件。<br>
<br>
再看看程序入口函数 main.cpp:<br>
<div class="code"> <span style=" color:#000080;">#include</span><span style=" color:#c0c0c0;">
</span><span style=" color:#008000;">"widget.h"</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QApplication></span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">main</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">argc</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">char</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span
style=" color:#000000;">argv</span><span style=" color:#000000;">[])</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QApplication</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">a</span><span style=" color:#000000;">(</span><span
style=" color:#000000;">argc</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">argv</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">show</span><span style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">a</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">exec</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
这个 main.cpp 代码结构与上一节的类似,main 函数内部先定义 Qt 应用程序入口,在定义一个全局类 Widget 的对象 w,然后显示 w
对象。最后是进入应用程序的事件循环。对于普通窗体程序,QtCreator 自动生成的 main.cpp 都是这样的。<br>
<br>
讲完 *.h 和 *.cpp ,最后来看看 pro 文件的代码:<br>
<div class="code"> <span style=" color:#008000;">#-------------------------------------------------</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">#</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">#</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">Project</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">created</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">by</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">QtCreator</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">2015-04-08T21:34:09</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">#</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">#-------------------------------------------------</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">QT</span><span style=" color:#c0c0c0;"> </span>+=<span
style=" color:#c0c0c0;"> </span>core<span style=" color:#c0c0c0;"> </span>gui</pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">greaterThan(<span
style=" color:#800080;">QT_MAJOR_VERSION</span>,<span style=" color:#c0c0c0;"> </span>4):<span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QT</span><span style=" color:#c0c0c0;"> </span>+=<span
style=" color:#c0c0c0;"> </span>widgets</pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">TARGET</span><span style=" color:#c0c0c0;"> </span>=<span
style=" color:#c0c0c0;"> </span>hellocreator</pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">TEMPLATE</span><span style=" color:#c0c0c0;"> </span>=<span
style=" color:#c0c0c0;"> </span>app</pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">SOURCES</span><span style=" color:#c0c0c0;"> </span>+=<span
style=" color:#c0c0c0;"> </span>main.cpp\</pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span>widget.cpp</pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">HEADERS</span><span style=" color:#c0c0c0;"> </span>+=<span
style=" color:#c0c0c0;"> </span>widget.h</pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">FORMS</span><span style=" color:#c0c0c0;"> </span>+=<span
style=" color:#c0c0c0;"> </span>widget.ui</pre>
</div>
井号 # 打头的是注释,表明这个 pro 文件是由 QtCreator 创建的,QtCreator 创建的 pro 文件和 qmake 命令创建的
pro 文件有区别,而且 QtCreator 创建的 pro 文件兼容性更好,所以推荐是用 QtCreator 生成 Qt 项目并编辑和构建项目。<br>
<div class="code">
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">QT</span><span style=" color:#c0c0c0;"> </span>+=<span
style=" color:#c0c0c0;"> </span>core<span style=" color:#c0c0c0;"> </span>gui</pre>
</div>
这一句是为项目添加 core (QtCore,核心模块)和 gui (QtGui,基础绘图模块)两个 Qt 模块。<br>
<div class="code">
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">greaterThan(<span
style=" color:#800080;">QT_MAJOR_VERSION</span>,<span style=" color:#c0c0c0;"> </span>4):<span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QT</span><span style=" color:#c0c0c0;"> </span>+=<span
style=" color:#c0c0c0;"> </span>widgets</pre>
</div>
这句是个判断句法,如果 Qt 库的主版本号大于 4 ,比如 Qt5 ,那就添加新的 Qt 模块
widgets(QtWidgets,控件和窗口类模块),如果项目使用的是 Qt4,那么就不添加 widgets 模块。这句是为了兼容性而设计的,Qt4
时代,它的控件和窗口类集成在 gui 模块里,在 Qt5 才将 widgets 从 gui 里单独分离出来的。<br>
<div class="code"><span style=" color:#800080;">TARGET</span><span style=" color:#c0c0c0;">
</span>=<span style=" color:#c0c0c0;"> </span>hellocreator
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">TEMPLATE</span><span style=" color:#c0c0c0;"> </span>=<span
style=" color:#c0c0c0;"> </span>app</pre>
</div>
TARGET 是指生成的目标程序名字,本项目生成的目标名字就是 hellocreator 。TEMPLATE 是指项目生成模板,指明是生成应用程序
app 还是库文件 lib,还有其他类型的生成模板,不常用就不枚举了。<br>
<div class="code"> <span style=" color:#800080;">SOURCES</span><span style=" color:#c0c0c0;">
</span>+=<span style=" color:#c0c0c0;"> </span>main.cpp\
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span>widget.cpp</pre>
</div>
SOURCES 指明项目里的源代码文件,有 main.cpp 和 widget.cpp
,这个对应边栏“项目”视图里的“源文件”虚拟目录。main.cpp 行尾的反斜杠 \ 是行拼接的意思,与 C++ 代码行尾的拼接反斜杠 \ 作用类似。<br>
<div class="code"> <span style=" color:#800080;">HEADERS</span><span style=" color:#c0c0c0;">
</span>+=<span style=" color:#c0c0c0;"> </span>widget.h</div>
HEADERS 指明项目里的头文件,有 widget.h ,这个对应边栏“项目”视图里的“头文件”虚拟目录。那么 ui_widget.h
跑哪去了?这个不用担心,ui_widget.h 会在项目生成时,由 Makefile 指定 uic 工具根据 widget.ui
编译而成,ui_widget.h 属于项目生成过程中的中间文件,没必要包含在 pro 文件里,把这些事情交给 Makefile 就行了。<br>
<div class="code"> <span style=" color:#800080;">FORMS</span><span style=" color:#c0c0c0;">
</span>+=<span style=" color:#c0c0c0;"> </span>widget.ui</div>
FORMS 指明项目里的 *.ui 文件,对应边栏“项目”视图里的“界面文件”虚拟目录。这个项目里只有一个主界面
widget.ui,以后会学习到在一个项目里使用多个 ui
文件,比如一个主界面配多个弹出的子对话框。项目代码讲解先到这里,接下来当然是生成该项目的目标程序了。<br>
<br>
<div class="os2">2.4.5 程序生成和运行</div>
<br>
用集成开发环境 QtCreator 编译生成程序是再简单不过的事了。一个按钮就够了。当然,得先认识认识 QtCreator 左下角的按钮:<br>
<center><img src="images/ch02/ch02-04-17.png" alt="codeedit"></center>
左下角四个按钮,第一个按钮是选择构建项目使用的 Qt 套件和构建目标程序的类型(Debug 或 Release)。<br>
第二个是运行按钮,快捷键是 Ctrl+R,如果还没构建项目或刚修改了代码,直接点击运行的话,QtCreator 会自动构建生成新的目标程序并运行。<br>
第三个是调试按钮,快捷键是 F5。调试程序之前,QtCreator 会自动构建生成最新的目标程序,并进入调试模式。在下一节专门讲解调试程序。<br>
第四个是构建按钮,快捷键是 Ctrl+B,只构建最新的目标程序,但不运行。<br>
如果只构建而不运行程序,就点第四个。一般都是构建后运行程序查看效果,可以直接点击第二个运行按钮,如果没问题发生,就会显示目标程序主界面:<br>
<center><img src="images/ch02/ch02-04-18.png" alt="run" width="800"></center>
从编译生成到运行,不需要自己敲命令,一个按钮搞定,这就是集成开发环境的好处。<br>
<br>
上面示范的是默认 Qt 套件,构建的是 Debug 类型的目标程序。如果需要构建 Release 版目标程序,点开左下角第一个按钮:<br>
<center><img src="images/ch02/ch02-04-19.png" alt="release"></center>
可以选择 Release 构建类型,然后再点击运行按钮就可以构建运行 Release 版本目标程序。上图是针对项目只用到单一 Qt
套件的,如果之前配置了多个 Qt 套件,看到的类似下图:<br>
<center><img src="images/ch02/ch02-04-20.png" alt="select"></center>
如果项目配置了多个可用的 Qt 套件,点开左下角第一个按钮后,会看到各个套件以及构建类型(Debug 和 Release),如果要切换 Qt
套件或构建类型,直接选中相应条目,然后点击运行按钮就行了。如果构建和运行时没出错,就会显示出构建好的目标程序界面。<br>
<br>
从集成开发环境构建和运行程序是很简单的事,但这些看起来简单的过程背后都发生了什么呢?<br>
我们点击 QtCreator 项目模式,可以看到项目配置界面:<br>
<center><img src="images/ch02/ch02-04-21.png" alt="project" width="800"></center>
在打开具体的项目之后,QtCreator 的项目模式才会变得可用。对于打开的项目,比如 hellocreator
项目,可配置的内容如上图顶上面显示的四大类,有“构建和运行”、“编辑器”、“代码风格”、“依赖关系”。最常用的就是“构建和运行”。在“构建和运行”配置里面,可以
看到 Qt 套件的名称,并且可以添加管理 Qt 套件。<br>
<br>
对于每个 Qt 套件,又可以分别配置构建时环境、命令和运行时环境、命令。如果需要给生成的可执行程序如 *.exe 附加命令参数,那就可以点击
Qt 套件名称下方的“运行”设置,给可执行程序附加参数。下面重点关注“构建”设置。<br>
<br>
在“构建设置”里,上方组合框里可以选择构建类型(Debug 或 Release)进行分别设置,并且可以自己添加新的构建类型(一般没必要)。<br>
<br>
接下来“概要”里面,QtCreator 默认使用影子构建方式(Shadow
build),这种构建项目的方式是将构建过程中的中间文件和目标程序都放到独立的构建目录中,实现源代码目录和构建目录的彻底分离,这对程序源代码的发布很方便,不会将
构建过程中的中间文件混杂进来。对于项目 hellocreator ,它的源代码路径是
D:\QtProjects\ch02\hellocreator,而上图中影子构建的目录是在
D:\QtProjects\ch02\build-hellocreator-Desktop_Qt_5_4_0_MinGW_32bit-Debug,源码文件夹和构
建文件夹都在父文件夹 ch02 里。影子构建目录的命名规则是:build-项目名-构建套件名-构建类型 。示范的项目名 hellocreator,套件名
Desktop Qt 5.4.0 MinGW 32bit,构建类型为 Debug,合成之后的构建目录里不能带空格,所以把空格都换成下划线,得到
build-hellocreator-Desktop_Qt_5_4_0_MinGW_32bit-Debug
。项目构建时生成的中间文件和最终的目标程序都可以在影子构建目录里找到。<br>
<br>
接着是“构建步骤”,上一节提过 qmake 编译程序的三板斧,因为 pro 文件已经由 QtCreator
生成好了,所以这时候编译程序只需要剩下的两板斧:①用 qmake 生成 Makefile 到构建目录;②在构建目录里面执行 make
(mingw32-make) 。对于这两板斧的细节可以点开 qmake 和 Make 两行右边的详情进行查看,这里不额外截图了,仅解释一下上图中
qmake 命令的选项参数:<br>
<ul>
<li>-r 选项是指递归检查项目文件夹的意思;</li>
<li>-spec win32-g++ 选项参数是指使用 win32-g++ 定制脚本来生成
Makefile,对于不同的编译器和操作系统平台会使用不同的定制脚本,win32-g++ 是专门针对 Windows 系统 MinGW
编译环境的定制脚本(实际的定制脚本位于 QTDIR/mkspecs/win32-g++ 文件夹里);</li>
<li>"CONFIG+=debug" 是指生成 debug 类型的目标程序,对于优化发行版,对应的就是
"CONFIG+=release",如果这两个 CONFIG 都不加,那么默认生成 release 类型的目标程序。</li>
</ul>
QtCreator 项目模式暂时介绍这些,接下来我们看看关于项目构建和项目运行时的实际情况。回到 QtCreator 编辑模式,点击最下面一排输出面板里
的“编译输出”面板,可以看到生成项目过程中的编译、链接命令:<br>
<center><img src="images/ch02/ch02-04-22.png" alt="compileoutput" width="800"></center>
QtCreator
实际使用的编译链接命令比我们上一节的编译链接命令复杂太多了,上一节使用的是极度精简的命令。如果项目的编译链接没有出问题,不用太在意“编译输出”面板里的东西,如果
编译链接过程出错了,就需要查看“编译输出”面板里的问题了。虽然 QtCreator
编译链接命令复杂,但大致过程和上一节最后那张生成过程图是类似的。“编译输出”面板里的命令这里不介绍了,对于初学者来说不用管的,反正是自动生成的,现在不用操心这么
复杂的事情。<br>
<br>
与“编译输出”面板相比,“应用程序输出”面板更为常用,对于调试信息的输出、打印到命令行的输出等,QtCreator 都会捕捉到,并显示到“应用程序输
出”面板,如下图所示:<br>
<center><img src="images/ch02/ch02-04-23.png" alt="appoutput" width="800"></center>
“应用程序输出”面板标题栏位置还有些小按钮,感兴趣的读者可以自己试试,有清空输出内容、重新运行程序、停止当前运行程序之类快捷功能。<br>
<br>
最后说明一下目标程序的运行环境,如果希望从集成开发环境为生成的目标程序加命令行参数,那么需要用到项目模式的“运行设置”:<br>
<center><img src="images/ch02/ch02-04-24.png" alt="runsetttings1" width="800"></center>
在项目模式,点击上面各个构建套件的“运行”,就会进入运行配置界面,可以看到上图几个关键的路径和参数设置:<br>
①Executable:可执行程序路径,或叫目标程序路径,生成的 exe 文件为 <br>
D:\QtProjects\ch02\build-hellocreator-Desktop_Qt_5_4_0_MinGW_32bit-Debug\debug\hellocreator.exe,<br>
如果进入该路径,直接运行 exe 文件,那么 exe 文件默认是无法正常运行的,因为缺少运行时依赖的动态库和环境变量。需要从开始菜单启动 Qt
命令行,然后从命令行启动 exe 才能正常运行。<br>
②Arguments:目标程序的命令行参数,可以在这里手动添加命令行参数,这样每次 QtCreator 启动目标程序时都会附加该参数。<br>
<span style="color: red; font-weight: bold;">③Working
directory:目标程序工作路径,这里需要特别注意,目标程序既不是从源代码路径启动,也不是从它自己的可执行程序路径启动,
而是从工作路径启动,这个工作路径默认与影子构建路径一样。
因此,如果在程序代码里面使用相对路径操作文件,如 "data.db",那么这个文件应该放到工作路径,这样目标程序从
QtCreator 启动时,才能找到相对路径里的文件。</span><br>
<br>
运行设置里面还有一个重要的设置就是 Run Environment,运行时环境变量的设置,我们标出其中重要的变量如下:<br>
<center><img src="images/ch02/ch02-04-25.png" alt="runsetttings2" width="800"></center>
读者一般对 PATH 环境变量比较熟悉,就是大量可执行程序 *.exe 和依赖库 *.dll 的路径,程序启动时会从 PATH 环境变量找寻依赖的
dll 并加载。Qt 也为 PATH 添加了自己的依赖库路径,新增的有三个路径:<br>
<ul>
<li>C:\Qt\Qt5.4.0\5.4\mingw491_32\lib;</li>
<li>C:\Qt\Qt5.4.0\5.4\mingw491_32\bin;</li>
<li>C:\Qt\Qt5.4.0\Tools\mingw491_32\bin;</li>
</ul>
第一个是编译时依赖库的路径,第二个是 Qt 库自己可执行程序和动态库路径,第三个是 MinGW 编译环境的可执行程序和动态库路径。<br>
<br>
除了 PATH 环境变量,Qt 库专属的 QTDIR 环境变量也很重要,Qt 程序运行时不仅依赖 *.dll ,还依赖 Qt
库里面的插件、翻译文件、设置文件等等,QTDIR 是 Qt 库的总目录,Qt 程序根据这个总目录自动去找寻子文件夹,子文件夹会包含 Qt
程序运行时依赖的其他东西。如果读者希望把 Qt 的依赖库集成到操作系统的环境变量,那么不仅要设置 PATH,还要设置正确的 QTDIR。QTIDR
通常就是 qmake.exe 所在文件夹的父文件夹,比如 qmake.exe 位于
C:\Qt\Qt5.4.0\5.4\mingw491_32\bin,那么 QTDIR 就是 C:\Qt\Qt5.4.0\5.4\mingw491_32
。<br>
<br>
本节内容就介绍到这,主 要是通过 HelloCreator 例子熟悉一下集成开发环境,下一节介绍程序大致的调试过程。<br>
<br>
<br>
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="width: 40%;">
<div style="text-align: center;"> <a href="ch02-03.htm"><img class="pic"
style="width: 32px; height: 32px;" alt="prev" src="images/pics/prev.png"></a></div>
</td>
<td style="width: 20%;">
<div style="text-align: center;"><a href="contents.htm"><img class="pic"
style="width: 32px; height: 32px;" alt="contents" src="images/pics/contents.png"></a></div>
</td>
<td style="width: 40%;">
<div style="text-align: center;"> <a href="ch02-05.htm"><img class="pic"
style="width: 32px; height: 32px;" alt="next" src="images/pics/next.png"></a></div>
</td>
</tr>
</tbody>
</table>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。