QT5基础教程(介绍,下载,安装,第一个QT程序)

栏目:游戏资讯  时间:2023-08-08
手机版

  http://c.biancheng.net/qt/

  Qt(官方发音 [kju:t],音同 cute)是一个跨平台的 C++ 开发库,主要用来开发图形用户界面(Graphical User Interface,GUI)程序,当然也可以开发不带界面的命令行(Command User Interface,CUI)程序。

  Qt 是纯 C++ 开发的,所以学好 C++ 非常有必要,对于不了解 C++ 的读者,我建议先阅读《C语言教程》,再阅读《C++教程》。C++ 是在C语言的基础上发展起来的,学完C语言就学了 C++ 的一半了。

  Qt 还存在 Python、Ruby、Perl 等脚本语言的绑定, 也就是说可以使用脚本语言开发基于 Qt 的程序。开源社区就是这样,好东西就会被派生扩展,到处使用, 越来越壮大。

  Qt 支持的操作系统有很多,例如通用操作系统 Windows、Linux、Unix,智能手机系统 Android、iOS、WinPhone, 嵌入式系统 QNX、VxWorks 等等。

  Qt 是什么

  Qt 图标(Logo)

  Qt 虽然经常被当做一个 GUI 库,用来开发图形界面应用程序,但这并不是 Qt 的全部;Qt 除了可以绘制漂亮的界面(包括控件、布局、交互),还包含很多其它功能,比如多线程、访问数据库、图像处理、音频视频处理、网络通信、文件操作等,这些 Qt 都已经内置了。

  Qt 是应用程序开发的一站式解决方案,有了 Qt,你就可以高枕无忧了!Qt 本身包含的模块也日益丰富, 一直有新模块和第三方模块加入进来。

  大部分应用程序都可以使用 Qt 实现,除了与计算机底层结合特别紧密的,例如驱动开发,它直接使用硬件提供的编程接口,而不能使用操作系统自带的函数库。

  1997年,Qt 被用来开发 Linux 桌面环境 KDE,大获成功,使 Qt 成为 Linux 环境下开发 C++ GUI 程序的事实标准。

  下面的程序都使用 Qt 开发:WPS、YY语音、Skype、豆瓣电台、虾米音乐、淘宝助理、千牛、暴雪的战网客户端、VirtualBox、Opera、咪咕音乐、Google地图、Adobe Photoshop Album 等。

  Linux 也是嵌入式的主力军,广泛应用于消费类电子、工业控制、军工电子、电信/网络/通讯、航空航天、汽车电子、医疗设备、仪器仪表等相关行业。

  Qt 虽然也支持手机操作系统,但是由于 Android 本身已经有 Java 和 Kotlin,iOS 本身已经有 Objective-C 和 Swift,所以 Qt 在移动端的市场份额几乎可以忽略。

  总起来说,Qt 主要用于桌面程序开发和嵌入式开发。

  Qt 目前支持主流的 Android、iOS、WinPhone 等智能机操作系统。MeeGo 是基于 Qt 开发的操作系统,由于被诺基亚抛弃了, 只剩一代绝版诺基亚 N9 手机。

  诺基亚手机部门出售给微软之后,大部分诺基亚手机系统开发人员都被遣散了。

  原来诺基亚的一部分人成立新的 Jolla(卓蓝)公司,发布了 MeeGo 的衍生版智能手机系统 Sailfish(旗鱼),相应的手机和平板也发布开卖了。另一拨人投靠了 Tizen(泰泽),Tizen 是英特尔和三星力推的智能手机系统,该系统整合了 Limo 和 MeeGo,因为 MeeGo 系统被诺基亚抛弃,英特尔其实是被出卖了,所以只能联合三星重造智能手机系统 Tizen。 目前基于 Tizen 的首款手机三星 Z1 在印度上市了。在 Tizen 阵营,国内有中兴、百度涉及了。Qt 开源项目里也有 Qt for Tizen 版本,有兴趣的可以去搜搜。

  Qt 公司有专门针对移动开发的商业版本,20 欧元或 25 美元一个月。不做商业可以无视这个,用开源版本也是可以开发如 Android、iOS、WinPhone 应用的。

  本教程关注的是传统桌面操作系统开发的,移动开发可以参考 Qt 官方的文档。

  说到 Qt 的发展史,那真是一波三折,几经卖身。

  Qt 最早是 1991 年由挪威的 Eirik Chambe-Eng 和 Haavard Nord 开发的, 他们随后于 1994 年 3 月 4 号正式成立奇趣科技公司(Trolltech)。Qt 原本是商业授权的跨平台开发库, 在 2000 年奇趣科技公司为开源社区发布了遵循 GPL(GNU General Public License)许可证的开源版本。

  在 2008 年,诺基亚公司收购了奇趣科技公司,并增加了 LGPL(GNU Lesser General Public License)的授权模式。诺基亚联合英特尔利用 Qt 开发了全新的智能手机系统 MeeGo,可惜遭遇了微软木马屠城,诺基亚被迫放弃了 MeeGo, 而 Qt 商业授权业务也于 2011 年 3 月出售给了芬兰 IT 服务公司 Digia。

  微软收购诺基亚

  当然好消息是 Digia 于 2014 年 9 月宣布成立 Qt Company 全资子公司,独立运营 Qt 商业授权业务。目前 Qt 公司大力推广移动平台开发和商业应用, 总的来说 Qt 历经曲折,现在算是步入正轨了。

  经过 20 多年的发展,Qt 已经成为最优秀的跨平台开发框架之一,在各行各业的项目开发中得到广泛应用。许多大型软件都是用 Qt 开发的,如 Autodesk Maya、Google Earth、Skype、WPS Office等。

  永远不要忽视微软帝国的威胁,作为软件业的一代霸主,任何人都不要天真地试图和它做朋友,因为霸主不可能有朋友。微软的木马屠城是所有诺基亚人和芬兰人的痛,希望读者们都记牢这条。

  之前提到 Qt 原本是商业授权软件,是怎么开源的呢?这就涉及 Qt 和 KDE 的纠葛了。

  KDE 是 Linux 操作系统的桌面环境,与 GNOME 桌面是类似的,作为开源桌面它们竞争的情况更为多见,有兴趣的读者请猛击《Linux桌面环境》了解更多。

  KDE 是采用 GPL 许可证发布的开源软件,而最初 Qt 是商业授权的,存在商业侵权风险,GNOME 则是基于开源 GTK 库的,没有什么商业风险,这一度是 GNOME 优越于 KDE 的特性。

  由于 Qt 的商业授权,KDE 社区一度混乱纠结,与此同时 GNOME 则如火如荼发展起来了。 KDE 毕竟算是亲儿子,被另一波人欺负,奇趣科技公司当然看不下去了,最后是奇趣科技公司为了赢得开发者的支持,为 Qt 增加了 GPL 的开源授权, 对于开源社区而言,遵循 GPL 使用 Qt 就不需要付费,这为 KDE 解决了燃眉之急。

  之后 KDE 桌面和 GNOME 都发展壮大起来,都做得越来越好了。

  除了商业授权,目前 Qt 的开源授权有两种,一种是 GPL 授权,另一种是 LGPL 授权(诺基亚收购后新增)。

  对这两种开源授权,简单来说,使用 GPL 版本的软件一定还是 GPL 的开源软件,无论是使用了 Qt 的程序代码还是修改了 Qt 库代码,都必须按照 GPL 来发布,这是 GPL 的传染性。

  GPL 是什么都要开源,这对商业软件应用是不利的,所以诺基亚增加了 LGPL 授权 (第一个 L 可以叫 Lesser 宽松版或 Library 开发库版)。使用 LGPL 授权就可以利用 Qt 官方动态链接库,而不必开放商业代码。只要不修改和定制 Qt 库,仅使用 Qt 官方发布的动态链接库就可以不开源,这是商业友好的授权模式。

  其实只要不是做商业,就不太需要关注用什么授权,以 GPL 授权发布程序代码就可以了。

  世界上的开源协议有很多,有兴趣的读者请猛击《开源协议是什么?有哪些?如何选择?》了解更多内容。

  最后请认准 Qt 官方网站(有时候访问速度很慢甚至不能访问,读者请自备梯子),可以查阅文档或者浏览资讯:https://www.qt.io/

  世界上的 GUI 库多如牛毛,有的跨平台,有的专属于某个操作系统;有的只有 UI 功能,有的还融合了网络通信、多媒体处理、数据库访问等底层功能。

  Windows 下的 GUI 解决方案比较多:

  基于 C++ 的有 Qt、MFC、WTL、wxWidgets、DirectUI、Htmlayout;基于 C# 的有 WinForm、WPF;基于 Java 的有 AWT、Swing;基于 Pascal 的 有Delphi;基于Go语言的有 walk 和 electron;还有国内初露头角的 aardio;Visual Basic 曾经很流行,现在逐渐失去了色彩;如果你有 Web 开发经验,也可以基于 Webkit 或 Chromium 将网页转换为桌面程序。 没有哪一种方案能够独霸 Windows,使用比较多的编程语言是 C++、C#、Java。

  用 Qt 来开发 Windows 桌面程序有以下优点:

  简单易学:Qt 封装的很好,几行代码就可以开发出一个简单的客户端,不需要了解 Windows API。资料丰富:资料丰富能够成倍降低学习成本,否则你只能去看源码,关于 DirectUI、Htmlayout、aardio 的资料就很少。漂亮的界面:Qt 很容易做出漂亮的界面和炫酷的动画,而 MFC、WTL、wxWidgets 比较麻烦。独立安装:Qt 程序最终会编译为本地代码,不需要其他库的支撑,而 Java 要安装虚拟机,C# 要安装 .NET Framework。跨平台:如果你的程序需要运行在多个平台下,同时又希望降低开发成本,Qt 几乎是必备的。 Qt 和 MFC 读者经常将 MFC 和 Qt 进行对比,MFC 只能应用在 Windows 平台,而 Qt 是跨平台的,一次编写,到处运行。

  另外,Qt 已经封装了底层细节,学习 Qt 将会非常简单;而 MFC 只是给 Windows API 加了一层包装,不了解 Windows API 也学不好 MFC,大家普遍反映 MFC 难学。

  我们不能简单地说 Qt 好还是 MFC 好,两者都有用武之地;但是初学者学习 Qt 会比较简单,不用应付那些烦人的 Windows API,很快就能开发出带有漂亮界面的应用程序。

  Linux 下常用的 GUI 库有基于 C++ 的 Qt、GTK+、wxWidgets,以及基于 Java 的 AWT 和 Swing。其中最著名的就是 Qt 和 GTK+:KDE 桌面系统已经将 Qt 作为默认的 GUI 库,Gnome 桌面系统也将 GTK+ 作为默认的 GUI 库。

  有兴趣的读者请猛击《Linux桌面系统》了解更多关于 KDE 和 Gnome 的内容。

  相比 GTK+,Qt 的功能更加强大,更新也很快,比较受人们追捧。

  Linux下各种GUI库对比图

  图1:Linux 下各种 GUI 库对比图

  Qt4 时代的主流就是传统部件(或叫控件)编程,所用的语言一般是 C++。 Qt5 诞生之时,正是手机移动设备蓬勃发展的时候,而传统的 C++ 部件编写的界面对手机应用程序非常方便,比如手机屏幕显示随意翻转, 这在传统桌面程序里基本遇不到,谁会将 22 寸显示器翻过来转过去呢。

  为了适应手机移动应用开发, Qt5 将 QML 脚本编程提到与传统 C++ 部件编程相同的高度,力推 QML 界面编程,当然 QML 主要用于手机移动应用程序。 QML 包含大量使用手机移动设备的功能模块,比如基本部件(QtQuick 模块)、GPS 定位、渲染特效、蓝牙、NFC、WebkKit 等等。

  QML 类似于网页设计的 HTML,是一种标记语言,我们可以借助 CSS 对它进行美化,也可以借助 JavaScript 进行交互。有 Web 开发经验的读者学习 QML 将非常轻松。

  使用 QML 开发界面主要有以下几个优点:

  QML 非常灵活,可以做出非常炫酷的效果,例如 QQ、360、迅雷等都不在话下。QML 是标记语言,见名知意,非常容易编写和阅读,大大提高了开发和维护效率。QML 界面简洁大气,有很多动画,适合移动端。不同平台下的 QML 使用相同的渲染机制,界面效果一致,不会随操作系统的不同而变化。 既然 QML 有这么多优点,我们是不是可以不学 C++,直接学习 QML 呢?

  非也!QML 只能用来进行界面设计和人机交互,也就是只能胜任 UI 部分,在底层仍然需要调用 C++ 编写的组件来完善功能,比如访问数据库、网络通信、多线程多进程、文件读写、图像处理、音频视频处理等都离不开 C++。

  另外,现阶段新生的 QML 还不如传统的 C++ 部件编程那样拥有丰富的开发组件,尤其缺乏复杂的企业级应用程序所必须的树等控件。这就决定了至少现阶段,真正大型的桌面程序仍然只能选择以 C++ 为主、QML 为辅的开发模式。

  相信大部分读者都没有 Web 开发经验,学习 QML 成本还是比较高的,不但要习惯 QML 这种标记性语言,还要学习 CSS 和 JavaScript。

  总的来说,C++ 对于 Qt 是不可或缺的,而 QML 只是一个加分项。

  本教程只讲解 C++ 部件编程 C++依旧是 Qt 的主要编程语言,Qt 5 也并没有忽略它,Qt 5 添加了很多新的 C++ API,而且会持续更新。引入 QML 只是 Qt 5 提供的另外一种选择,并不是让它成为唯一的选择。

  C++ 是 Qt 的基础,无论如何都要掌握,本教程也只讲解传统的 C++ 部件编程,不讲解 QML。

  Qt 体积很大,有 1GB~3GB,官方下载通道非常慢,相信很多读者会崩溃,所以建议大家使用国内的镜像网站(较快),或者使用迅雷下载(很快)。

  作为 Qt 下载教程,本文会同时讲解以上三种下载方式。

  Qt 官网有一个专门的资源下载网站,所有的开发环境和相关工具都可以从这里下载,具体地址是:http://download.qt.io/

  Qt官方下载网站截图

  图1:Qt 官方下载网站截图

  目录说明archive各种 Qt 开发工具安装包,新旧都有(可以下载 Qt 开发环境和源代码)。community_releases社区定制的 Qt 库,Tizen 版 Qt 以及 Qt 附加源码包。development_releases开发版,有新的和旧的不稳定版本,在 Qt 开发过程中的非正式版本。learning有学习 Qt 的文档教程和示范视频。ministro迷你版,目前是针对 Android 的版本。official_releases正式发布版,是与开发版相对的稳定版 Qt 库和开发工具(可以下载Qt开发环境和源代码)。onlineQt 在线安装源。snapshots预览版,最新的开发测试中的 Qt 库和开发工具。 archive 和 official_releases 两个目录都有最新的 Qt 开发环境安装包,我们以 archive 目录里的内容为例来说明。点击进入 archive 目录,会看到四个子目录:

  archive的四个子目录

  图2:进入 archive 目录

  目录说明vsaddin这是 Qt 针对 Visual Studio 集成的插件,本教程基本不使用 Visual Studio ,所以不需要插件。qtcreator这是 Qt 官方的集成开发工具,但是 qtcreator 本身是个空壳,它没有编译套件和 Qt 开发库。 除了老版本的 Qt 4 需要手动下载 qtcreator、编译套件、Qt 开发库进行搭配之外,一般用不到。对于我们教程压根不需要下载它,因为 Qt 5 有专门的大安装包,里面包含开发需要的东西,并且能自动配置好。qt这是 Qt 开发环境的下载目录,我们刚说的 Qt 5 的大安装包就在这里面。online_installers在线安装器,国内用户不建议使用,在线安装是龟速,还经常断线。我们教程采用的全部是离线的大安装包。 我们再进入 qt 子目录 ,看到如下列表:

  qt子目录

  图3:进入 qt 子目录

  上图没有列完整,这个 qt 目录包含了所有的 Qt 版本,从 1.0 到目前的 5.12 。

  由于 Qt 5.9 是一个长期技术支持版本(Long Term Support,LTS),在未来几年里都将有更新支持,因此,本教程以 Qt 5.9 LTS 版本为例进行讲解,并且所有实例程序均使用 Qt 5.9 编译测试通过。

  Qt 的上一个 LTS 版本是 5.6,它其实已经超出支持期了。

  进入 5.9 目录,会看到各种子版本:

   qt 5.9 子目录

  图4:Qt 5.9 的各个子版本

  这里解释一下 Qt 的版本号,比如 5.9.8 是完整的 Qt 版本号,第一个数字 5 是大版本号(major),第二个数字 9 是小版本号(minor),第三个数字 8 是补丁号(patch)。 只要前面两个数字相同,Qt 的特性就是一致的,最后的数字是对该版本的补丁更新。也就是说本教程对 5.9.* 系列的 Qt 都是通用的,下载 5.9.* 任意一个版本都可以,这里我们以下载 5.9.0。

  点击 5.9.0,进入子目录:

  Qt 5.9.0 下载页面

  图5:Qt 5.9.0 下载页面

  根据不同的操作系统,选择不同的安装包即可,不用管源码包,除非你想自己编译或者阅读源码。

  我们以 Windows 安装包(qt-opensource-windows-x86-5.9.0.exe)讲解一下 Qt 安装包命名规则,其中:

  opensource 是指开源版本;windows 是指开发环境的操作系统;x86 是指 32 位系统;5.9.0 是 Qt 版本号。 请读者注意图5中最后一栏的 Details 链接(红色方框圈起来的地方)。点击 Details 链接可以进入详情页,在该页面可以看到文件的大小、校验和以及世界各地镜像下载链接(这才是重点)。

  国内镜像下载链接

  图6:国内镜像下载链接

  可以清楚地看到,Qt 在国内的有三个镜像网站可以下载,点击这些地址中的一个就可以下载,从国内镜像网站下载速度快一些。

  国内镜像网站 这里给大家推荐几个国内著名的 Qt 镜像网站,主要是各个高校的:

  中国科学技术大学:http://mirrors.ustc.edu.cn/qtproject/清华大学:https://mirrors.tuna.tsinghua.edu.cn/qt/北京理工大学:http://mirror.bit.edu.cn/qtproject/中国互联网络信息中心:https://mirrors.cnnic.cn/qt/ 国内镜像网站的结构和官方是类似的,我们在第一部分已经分析过了,这里不再赘述。

  将 Qt 软件的下载地址复制到迅雷的下载框,如果迅雷官方有资源,就会自动识别,下载速度就很快了。

  如何找到 Qt 软件的下载地址呢?以清华大学开源软件镜像站为例,进入 Qt 5.9.0 的下载目录(https://mirrors.tuna.tsinghua.edu.cn/qt/archive/qt/5.9/5.9.0/),在某个链接处单击鼠标右键,会弹出一个菜单,选择“复制链接地址”,如下图所示:

  找到Qt下载地址

  图7:找到 Qt 下载地址

  这样就把 Qt 5.9.0 的下载地址(具体为 https://mirrors.tuna.tsinghua.edu.cn/qt/archive/qt/5.9/5.9.0/qt-opensource-windows-x86-5.9.0.exe)复制到了剪切板,然后再粘贴到迅雷的下载框:

  把Qt下载地址粘贴到迅雷下载框

  图8:把Qt下载地址粘贴到迅雷下载框

  点击“立即下载”按钮,稍等片刻,迅雷会自动匹配到资源,速度飞快。

  下载速度 2.7MB/s

  图9:下载速度 2.7MB/s

  注意,常用的 Qt 版本一般都能匹配到资源,但是不保证每个版本都能匹配到资源,上面的例子仅对清华大学镜像站的 Qt 5.9.0 Windows 版(https://mirrors.tuna.tsinghua.edu.cn/qt/archive/qt/5.9/5.9.0/qt-opensource-windows-x86-5.9.0.exe)有效。

  对 Qt 版本更新感兴趣的读者请访问 Qt wiki 网站,地址为:https://wiki.qt.io/Main

  Qt wiki 网站会显示最新的正式版、LTS 版、正在开发中的版本等等,比主站(https://www.qt.io/)靠谱多了。Qt 主站因为商业推广的原因,安装包的下载步骤非常繁琐。

  本节介绍 Qt 5.9.0 在 Windows 平台下的安装,请提前下载好 Qt 5.9.0。不知道如何下载 Qt 的读者请转到:Qt下载(多种下载通道+所有版本)

  目前较高版本的 Qt 仅支持 Win7 及其以后的操作系统,不支持 Win XP;使用 Win XP 的读者请安装 Qt 5.5.1 之前的版本。

  Qt 占用的存储空间很大,安装之前建议先准备好 8GB 以上的磁盘空间。对于目前 Qt 最新版开发环境,如果不安装源代码包,实际占用大约 5.5GB;如果选择安装源码包,大约占用 7.5GB。

  双击下载得到的 qt-opensource-windows-x86-5.9.0.exe 即可开始安装。Qt 的安装过程和普通的 Windows 软件一样,按照向导进行操作即可。

  关于 Qt 的安装需要说明以下几点。

  Qt 在安装过程中会提示用户进行注册和登录,不用理会,跳过(Skip)即可,实际开发时不需要登录。

  Qt 安装过程中提示用户注册

  图1:Qt 安装过程中提示用户注册

  指定Qt安装路径

  图2:指定 Qt 安装路径

  Qt 允许用户自定义安装路径,但是请注意,安装路径不能带空格、中文字符或者其它任何特殊字符。

  另外,该界面还会询问是否关联特定的文件类型。如果关联(默认是关联的),特定后缀的文件(包括 .cpp 文件)默认使用 Qt 打开。我喜欢使用纯文本编辑器(例如 Sublime Text)来打开 C++ 源文件,所以我取消了该选项,读者根据自己的实际情况定夺。

  Qt 安装过程中最关键的一步是组件的选择,请看下图:

  Qt组件

  图3:Qt 组件

  Qt 的安装组件分为两部分:一部分是“Qt 5.9”分类下的,该分类包含的是真正的 Qt 开发库组件;另一部分是“Tools”分类下的,该分类包含的是集成开发环境和编译工具。

  “Qt 5.9”分类下的开发组件组件说明MinGW 5.3.0 32 bit编译器模块。MinGW 是 Minimalist GNU for Windows 的缩写,MinGW 是 Windows 平台上使用的 GNU 工具集导入库的集合。是本教程使用 MinGW 编译,所以必须安装。UWP ***UWP 是 Windows 10 中 Universal Windows Platform 的简称,有不同编译器类型的 UWP,属于 MSVC 编译器生成的 Qt 库。如果不是开发 UWP 应用程序,就不需要,直接忽略。MSVC ***针对 Windows 平台上的 MSVC 编译器的 Qt 组件,如 msvc2015 32-bit 和 msvc2015 64-bit 等。安装该组件需要计算机上已经安装相应版本的 Visual Studio。如果你不使用 MSVC 编译器进行开发,就不用安装。本教程使用 MinGW 编译组件,所以不用安装 MSVC *** 组件。Android ***这是针对安卓应用开发的 Qt 库,如果读者有安卓开发这方面需求可以自己选择安装,一般情况下用不到。SourcesQt 的源代码包,除非你想阅读 Qt 的源码,否则不用安装。Qt ***Qt 的附加模块,大部分建议安装,这些附加模块括号里的 TP 是指 Technology Preview ,技术预览模块的意思,还处在功能测试阶段,不是正式版模块;附加模块括号里的 Deprecated 是指抛弃的旧模块,兼容旧代码使用的,一般用不到。这些附加模块读者可以选择部分或都勾选了安装,占用空间不大。 部分组件说明:Qt Charts 是二维图表模块,用于绘制柱状图、饼图、曲线图等常用二维图表。Qt Data Visualization 是三维数据图表模块,用于数据的三维显示,如散点的三维空间分布、三维曲面等。Qt Scritp(Deprecated)是脚本模块,已被抛弃,不建议安装。“Tools”分类下的开发组件组件说明Qt Creator 4.3.0这是集成开发环境,强制安装的,以后所有的项目和代码都在 Qt Creator 里面新建和编辑。Qt Creator 4.3.0 CDB Debugger surpport用于和 CDB 调试工具对接,默认安装,一般用于调试 VC 编译的 Qt 程序。MinGW 5.3.0这是开源的编译器套件,这本教程必须用到的,需要读者勾选安装。Strawberry Perl 5.22.1.3用于编译 Qt 源代码的 Perl 开发环境,不需要安装。如果读者以后用到,也可以另外手动安装,在搜索引擎搜索 Strawberry Perl 关键词,去 Strawberry Perl 官网下载最新的安装包是一样用的。 选择完了组件,根据向导一步一步操作就可以了。安装完成后,在 Windows“开始”菜单中会看到 Qt 5.9.0 程序组。

  Qt 5.9.0所包含的程序

  图4:Qt 5.9.0 所包含的程序

  程序说明Qt Creator 4.6.2 (Enterprise)Qt 的集成开发环境,本教程就使用它来创建和管理 Qt 项目。Assistant(Qt 助手)用来查看帮助文档,已被集成在 Qt Creator 中。Designer(Qt 设计师)图形界面可视化编辑工具,已被集成在 Qt Creator 中,在 Qt Creator 中编辑或创建界面文件时,就可以自动打开。Linguist(Qt 语言家)多国语言翻译支持工具,可以用来编辑语言资源文件,在开发多语言界面的应用程序时会用到。Qt 5.11.1 for Desktop (MinGW 5.3.0 32bit)Qt 命令行工具,用来配置 Qt 开发环境(主要是设置 PATH 变量)。 了解 Qt 安装目录的结构虽然不是编程必须的,但是它能练就我们的内功,让我们对 Qt 的编程环境了如指掌。Windows 和 Linux 下 Qt 安装目录的结构非常相似,我们以 Windows 为例进行讲解,Linux 不再赘述。

  不同版本 Qt 的安装目录结构大同小异,本节我们以 Qt 5.9.0 为例来说明,如下图所示。

  Qt 安装目录的结构

  图1:Qt 安装目录的结构

  为了方便描述,下文我们使用表示 Qt 的安装目录。

  注意,~5.9 和 ~Tools 目录下都有 mingw53_32 目录(图中我用红色标出来了),但是两者是有区别的:

  ~5.9mingw53_32 目录包含的是 Qt 的类库文件,例如头文件、静态库、动态库等,这些类库文件使用 MinGW 工具集编译而成。~Toolsmingw53_32 目录包含的是 MinGW 工具集,例如编译器 g++、链接器 ld、make 工具、打包工具 ar 等。 QtCreator 是个例外,QtCreator 使用 MSVC2015 编译生成的,所以安装目录里有一个 vcredist 文件夹存储 VC 运行库安装文件。

  最后的 MaintenanceTool.exe ,对于离线安装包,它只能用于删除软件包,如果 Qt 开发环境是用在线安装方式装的,这个工具还可以管理开发环境组件和升级组件。

  Qt 类库的帮助文件位于 Docs 文件夹里,需要用 Qt Assistant 工具才能查看。

  Examples 里是示例代码,可以用 QtCreator 集成开发环境打开各个示例。

  下面我们再探究一下 Qt 类库目录(~5.9mingw53_32)的结构,如下图所示。

  Qt 类库目录

  图2:Qt 类库目录

  图上列的比较有限,不一定全面,主要是教大家熟悉一下 Qt 的开发环境。

  Qt 不是凭空产生的,它是基于现有工具链打造而成的,它所使用的编译器、链接器、调试器等都不是自己的,Qt 官方只是开发了上层工具。下面我们分几个部分讲解 Qt 使用到的工具链。

  在上个世纪八十年代,计算机都是奢侈品,操作系统里最著名的是 Unix 家族, 当时还没有 Windows、Linux 之类的,Unix 系统都是商业软件,里面的应用软件也是商业软件, 全是封闭的环境。

  系统程序员 Richard M. Stallman (RMS) 在此环境下创立了与众不同的 GNU 项目 (GNU’s Not Unix) , 以及推进自由软件发展的 Free Software Foundation (FSF) 自由软件基金会。

  GNU 项目是为了创建自由的类 Unix 系统,也因此开发出来很多开源的系统工具,其中非常著名的就是 GCC (GNU Compiler Collection,GNU编译器套件)。

  现在我们知道,GUN 开发类 Unix 系统的项目失败了,但是它开发的一系列工具集却用到了后来的 Linux 内核上,两者结合形成了今天的各种 Linux 发行版,有兴趣的读者请转到《Linux和UNIX的关系及区别》了解更多。

  在 GNU 工具集里面,开发时常见到的几个罗列如下(这些工具通常位于 Linux 或 Unix 系统里的 /usr/bin/ 目录):

  工具说明gccGNU C 语言编译器。g++GNU C++ 语言编译器。ldGNU 链接器,将目标文件和库文件链接起来,创建可执行程序和动态链接库。ar生成静态库 .a ,可以编辑和管理静态链接库。make生成器,可以根据 makefile 文件自动编译链接生成可执行程序或库文件。gdb调试器,用于调试可执行程序。ldd查看可执行文件依赖的共享库(扩展名 .so,也叫动态链接库)。 原本 GNU 工具只在 Linux/Unix 系统里才有,随着 Windows 系统的广泛使用, 为了在 Windows 系统里可以使用 GNU 工具,诞生了 MinGW(Minimalist GNU for Windows) 项目,利用 MinGW 就可以生成 Windows 里面的 exe 程序和 dll 链接库。

  需要注意的是,MinGW 与 Linux/Unix 系统里 GNU 工具集的有些区别:

  MinGW 里面工具带有扩展名 .exe, Linux/Unix 系统里工具通常都是没有扩展名的。MinGW 里面的生成器文件名为 mingw32-make.exe,Linux/Unix 系统里就叫 make。MinGW 在链接时是链接到 *.a 库引用文件,生成的可执行程序运行时依赖 *.dll,而 Linux/Unix 系统里链接时和运行时都是使用 *.so 。 另外 MinGW 里也没有 ldd 工具,因为 Windows 不使用 .so 共享库文件。如果要查看 Windows 里可执行文件的依赖库,需要使用微软自家的 Dependency Walker 工具。Windows 里面动态库扩展名为 .dll,MinGW 可以通过 dlltool 来生成用于创建和使用动态链接库需要的文件,如 .def 和 .lib。

  MinGW 原本是用于生成 32 位程序的,随着 64 位系统流行起来, 从 MinGW 分离出来了 MinGW-w64 项目,该项目同时支持生成 64 位和 32 位程序。Qt 的 MinGW 版本库就是使用 MinGW-w64 项目里面的工具集生成的。

  MSYS(Minimal SYStem) 另外提一下,由于 MinGW 本身主要就是编译链接等工具和头文件、库文件,并不包含系统管理、文件操作之类的 Shell 环境, 这对希望用类 Unix 命令的开发者来说还是不够用的。 所以 MinGW 官方又推出了 MSYS(Minimal SYStem),相当于是一个部署在 Windows 系统里面的小型 Unix 系统环境, 移植了很多 Unix/Linux 命令行工具和配置文件等等,是对 MinGW 的扩展。

  MSYS 对于熟悉 Unix/Linux 系统环境或者要尝试学习 Unix/Linux 系统的人都是一种便利。MSYS 和 MinGW 的安装升级都是通过其官方的 mingw-get 工具实现,二者是统一下载安装管理的。

  对于 MinGW-w64 项目,它对应的小型系统环境叫 MSYS2(Minimal SYStem 2),MSYS2 是 MSYS 的衍生版,不仅支持 64 位系统和 32 位系统,还有自己的独特的软件包管理工具,它从 Arch Linux 系统里移植了 pacman 软件管理工具,所以装了 MSYS2 之后,可以直接通过 pacman 来下载安装软件,而且可以自动解决依赖关系、方便系统升级等。装了 MSYS2 之后,不需要自己去下载 MinGW-w64,可以直接用 pacman 命令安装编译链接工具和 git 工具等。

  MinGW 项目主页(含 MSYS): http://www.mingw.org/

  MinGW-w64 项目主页: https://sourceforge.net/projects/mingw-w64/

  MSYS2 项目主页: https://sourceforge.net/projects/msys2/

  CMake(Cross platform Make)是一个开源的跨平台自动化构建工具, 可以跨平台地生成各式各样的 makefile 或者 project 文件, 支持利用各种编译工具生成可执行程序或链接库。

  CMake 自己不编译程序, 它相当于用自己的构建脚本 CMakeLists.txt,叫各种编译工具集去生成可执行程序或链接库。

  一般用于编译程序的 makefile 文件比较复杂,自己去编写比较麻烦, 而利用 CMake ,就可以编写相对简单的 CMakeLists.txt ,由 CMake 根据 CMakeLists.txt 自动生成 makefile,然后就可以用 make 生成可执行程序或链接库。

  本教程里面是使用 Qt 官方的 qmake 工具生成 makefile 文件,没有用 CMake。这里之所以提 CMake,是因为整个 KDE 桌面环境的茫茫多程序都是用 CMake 脚本构建的,另外跨平台的程序/库如 Boost C++ Libraries、OpenCV、LLVM、Clang 等也都是用 CMake 脚本构建的。以后如果接触到这些东西,是需要了解 CMake 的。

  CMake 项目主页:https://cmake.org/

  KDE 项目主页:https://www.kde.org/

  Qt 官方的开发环境安装包里有自己专门的开发工具,之前用过 qmake 命令。qmake 是 Qt 开发最核心的工具,既可以生成 Qt 项目文件 .pro ,也可以自动生成项目的 Makefile 文件。

  这里将常用的 Qt 开发工具列表如下:

  工具说明qmake核心的项目构建工具,可以生成跨平台的 .pro 项目文件,并能依据不同操作系统和编译工具生成相应的 Makefile,用于构建可执行程序或链接库。uicUser Interface Compiler,用户界面编译器,Qt 使用 XML 语法格式的 .ui 文件定义用户界面,uic 根据 .ui 文件生成用于创建用户界面的 C++ 代码头文件,比如 ui_*****.h 。mocMeta-Object Compiler,元对象编译器,moc 处理 C++ 头文件的类定义里面的 Q_OBJECT 宏,它会生成源代码文件,比如 moc_*****.cpp ,其中包含相应类的元对象代码,元对象代码主要用于实现 Qt 信号/槽机制、运行时类型定义、动态属性系统。rccResource Compiler,资源文件编译器,负责在项目构建过程中编译 .qrc 资源文件,将资源嵌入到最终的 Qt 程序里。qtcreator集成开发环境,包含项目生成管理、代码编辑、图形界面可视化编辑、 编译生成、程序调试、上下文帮助、版本控制系统集成等众多功能, 还支持手机和嵌入式设备的程序生成部署。assistantQt 助手,帮助文档浏览查询工具,Qt 库所有模块和开发工具的帮助文档、示例代码等都可以检索到,是 Qt 开发必备神器,也可用于自学 Qt。designerQt 设计师,专门用于可视化编辑图形用户界面(所见即所得),生成 .ui 文件用于 Qt 项目。linguistQt 语言家,代码里用 tr() 宏包裹的就是可翻译的字符串,开发人员可用 lupdate 命令生成项目的待翻译字符串文件 .ts,用 linguist 翻译多国语言 .ts ,翻译完成后用 lrelease 命令生成 .qm 文件,然后就可用于多国语言界面显示。qmlscene在 Qt 4.x 里是用 qmlviewer 进行 QML 程序的原型设计和测试,Qt 5 用 qmlscene 取代了旧的 qmlviewer。新的 qmlscene 另外还支持 Qt 5 中的新特性 scenegraph 。 本节我们来介绍一下使用 Qt 编程过程中常用的术语和名字,它们不一定专属于 Qt,在其它的 C/C++ 开发过程中也会使用到。

  Project 的中文翻译是“项目”或者“工程”,这里的项目是指为实现某个相对独立功能的程序代码合集,这些代码不单单是放在一块,而是有相互之间的关联性,并且有专门负责管理该项目的项目文件,比如:

  Qt 使用 .pro 文件管理项目;VC++ 则使用 .vcproj 作为项目文件。 集成开发环境通常都是依据项目文件(.pro/.vcproj)管理和构建项目。

  即生成脚本,虽然可以直接调用编译器如 g++ 编译程序,但是如果项目里的代码文件变多了,哪些代码文件更新了需要重新编译,哪些代码没有改不需要重新编译等等,靠程序员自己记忆去处理是比较麻烦的事,还有哪些代码需要预处理或是链接哪些库文件, 这些都是繁杂的过程。为了规范程序的编译生成过程,产生了规范化的生成脚本,就是 Makefile,生成器 make 可以依据规范的 Makefile 自动生成目标程序或库文件。

  简单的说,就是定义好 Makefile ,让程序员只需要去关注如何编写代码,而生成程序过程中的脏活累活都交给 make 程序。

  现在 Makefile 通常都有工具自动生成,如 qmake 工具, 这样就大量减轻了程序员的负担。

  Debug 即调试,Release 即发行。代码编写之后,生成的目标程序或库文件通常不会绝对正确,或多或少有些毛病(bug), 因此需要进行纠错调试(Debug)。调试过程中需要源代码和二进制目标程序之间一一对应的关系, 这样才能定位到错误代码,所以 Debug 版本的程序是臃肿而不进行优化的。

  与之相对的是 Release 发行版,在纠正了发觉到的错误后,需要发布程序用于实际用途,实际应用时强调运行效率高,减少冗余代码,因此会对二进制程序进行大量优化,提升性能。这样发布的二进制目标程序就是 Release 版。

  Debug 版本和 Release 版本使用的库文件不一样:

  Debug 版本程序通常链接的也是 Debug 版本的库文件,比如 libQt5Guid.a/Qt5Guid.dll,库文件的简短名(不含扩展名)都是以 d 结尾的,Debug 库通常都比较大 。Release 版本程序链接的通常就是 Release 版本的库文件,Release 版本库文件名字比 Debug 版本库文件少一个字母 d ,如 libQt5Gui.a/Qt5Gui.dll,而且 Release 版本库一般都比 Debug 版本小很多,运行效率也高很多。 时代在变化,C++ 标准也在前进。C++ 正式公布标准有 C++98、C++03、C++11。最新的 C++11 标准是2011年8月12日公布的,在公布之前该标准原名为 C++0x 。这是一次较大的修订和扩充,建议读者专门学一下。

  Qt 从 4.8 版本就开始用 C++11 新特性了。编译器里面开始支持 C++11 的版本是 MSVC 2010、GCC 4.5、Clang 3.1,这之后版本的编译器都在逐步完善对 C++11 的支持,现在新版本编译器对新标准的支持都比较全面了。

  Qt 官方在编译 Qt5 库的时候都是开启 C++11 特性的,如果我们要在自己项目代码启用新标准,需要在 .pro 文件里面添加一行:

  CONFIG += c++11

  如果是 Qt4 版本则是添加:

  gcc:CXXFLAGS += -std=c++0x

  MSVC 编译器默认开启 C++11 特性,GCC(g++命令)则需要自己添加选项 -std=c++0x ,上面 CXXFLAGS 就是为 GCC 编译器(g++命令)添加 -std=c++0x 选项。

  Dynamic Link 即动态链接,Static Link 即静态链接。

  动态链接库 目标程序通常都不是独立个体,生成程序时都需要链接其他的库,要用到其他库的代码。对于多个程序同时运行而言,内存中就可能有同一个库的多个副本,占用了太多内存而干的活差不多。

  为了优化内存运用效率,引入了动态链接库(Dynamic Link Library),或叫共享库(Shared Object)。使用动态链接库时,内存中只需要一份该库文件,其他程序要使用该库文件时,只要链接过来就行了。由于动态库文件外置,链接到动态库的目标程序相对比较小,因为剥离了大量库代码,而只需要一些链接指针。

  使用动态库,也意味着程序需要链接到如 *.dll 或 *.so 文件,得提前装好动态库文件,然后目标程序才能正常运行。

  静态链接库 静态库就是将链接库的代码和自己编写的代码都编译链接到一块,链接到静态库的程序通常比较大,但好处是运行时依赖的库文件很少,因为目标程序自己内部集成了很多库代码。

  库文件后缀 Linux/Unix 系统里静态库扩展名一般是 .a,动态库扩展名一般是 .so 。Windows 系统里 VC 编译器用的静态库扩展名一般是 .lib,动态库扩展名一般是 .dll 。

  MinGW 比较特殊,是将 GNU 工具集和链接库从 Linux/Unix 系统移植到 Windows 里, 有意思的情况就出现了,MinGW 使用的静态库扩展名为 .a ,而其动态库扩展名则为 .dll, .a 仅在生成目标程序过程中使用,.dll 则是在目标程序运行时使用。

  Explicit Linking 即显式链接,Implicit Linking 即隐式链接,这两种都是动态链接库的使用方式。

  动态链接库通常都有其导出函数列表, 告知其他可执行程序可以使用它的哪些函数。可执行程序使用这些导出函数有两种方式:一是在运行时使用主动加载动态库的函数,Linux 里比如用 dlopen 函数打开并加载动态库,Windows 里一般用 LoadLibrary 打开并加载动态库,只有当程序代码执行到这些函数时,其参数里的动态库才会被加载,这就是显式链接。显式链接方式是在运行时加载动态库,其程序启动时并不检查这些动态库是否存在。

  隐式链接是最为常见的,所有的编译环境默认都是采用隐式链接的方式使用动态库。隐式链接会在链接生成可执行程序时就确立依赖关系,在该程序启动时,操作系统自动会检查它依赖的动态库,并一一加载到该程序的内存空间,程序员就不需要操心什么时候加载动态库了。比如 VC 编译环境,链接时使用动态库对应的 .lib 文件(包含动态库的导出函数声明,但没有实际功能代码),在 .exe 程序运行前系统会检查依赖的 .dll,如果找不到某个动态库就会出现类似下图对话框:

  找不到动态链接库

  MinGW 是将动态库的导出函数声明放在了 .a 文件里,程序运行依赖的动态库也是 .dll 。

  请注意,VC 链接器使用的 .lib 文件分两类,一种是完整的静态库,体积比较大,另一种是动态库的导出声明,体积比较小。MinGW 链接器使用的 .a 文件也是类似的,Qt 官方库都是按照动态库发布的,静态库只有自己编译才会有。

  启动 Qt Creator,出现如图 1 所示的主窗口:

  Qt Creator主窗口

  图 1 Qt Creator主窗口

  Qt Creator 的界面很简洁。上方是主菜单栏,左侧是主工具栏,窗口的中间部分是工作区。根据设计内容不同,工作区会显示不同的内容。

  图 1 是在左侧主工具栏单击“Welcome(欢迎)”按钮后显示实例的界面。这时工作区的左侧有 “Projects”、“Examples(示例)”、“Tutorials(教程)”、“Get Started Now”几个按钮,单击后会在主工作区显示相应的内容:

  单击“Projects”按钮后,工作区显示新建项目按钮和最近打开项目的列表。单击“Examples(示例)”按钮后,工作区显示 Qt 自带的大量实例,选择某个实例就可以在 Qt Creator 中打开该项目源程序。单击“Tutorials(教程)”按钮后,工作区显示各种视频教程,查看视频教程需要联网并使用浏览器打开。单击“Get Started Now”按钮,工作区显示“Qt Creator Manual”帮助主题内容。 主窗口左侧是主工具栏,主工具栏提供了项目文件编辑、窗体设计、程序调试、项目设置等各种功能按钮。

  对 Qt Creator 可以进行一些设置,如刚安装好的 Qt Creator 界面语言可能是中文,也可以选择将 Qt Creator 的界面语言设置为英文。

  Options 的 Build&Run 设置页面

  图 2 Options 的构建和运行设置页面

  单击 Qt Creator 菜单栏的 菜单项会打开选项设置对话框(如图 2 所示)。对话框的左侧是可设置的内容分组,单击后右侧出现具体的设置界面。常用的设置包括以下几点:

  Environment(环境) 设置:在 Interface 页面可以设置语言和主题,本教程全部以中文界面的 Qt Creator 进行讲解,所以语言选择为 Chinese(China);为了使界面抓图更清晰,设置主题为 Flat Light。更改语言和主题后需要重新启动 Qt Creator 才会生效。Text Editor(文本编辑器)设置:在此界面可以设置文本编辑器的字体,设置各种类型文字的字体颜色,如关键字、数字、字符串、注释等字体颜色,也可以选择不同的配色主题。编辑器缺省字体的大小为 9,可以修改得大一些。Build & Run(构建和运行)设置:图 2 显示的是 Build & Run 的设置界面,它有以下几个页面。 Kits(构建套件)页面显示 Qt Creator 可用的编译工具。Qt Versions 页面显示安装的 Qt 版本。Compliers(编译器)页面显示系统里可用的 C 和 C++ 编译器,由于安装了 MinGW 和 Visual Studio 2015,Qt Creator 会自动检测出这些编译器。Debuggers 页面显示 Qt Creator 自动检测到的调试器,有 GNU gdb for MinGW 调试器和 Windows 的 CDB 调试器。 注意,如果只是在计算机上安装了 ,图 2 Kits 显示的界面上 MSVC2015 的两个编译器的图标会变为带有感叹号的一个黄色图标。Debuggers 页面没有 Windows 的 CDB 调试器,可以用 MSVC 编译器对 Qt Creator 编写的程序进行编译,但是不能调试,这是因为缺少了 。这个 SDK 不会随 Visual Studio 一同安装,需要从 Microsoft 网站上下载。可以下载 ,安装后重启计算机即可。

  学习一种编程语言或编程环境,通常会先编写一个“Hello World”程序。我们也用 Qt Creator 编写一个“Hello World”程序,以初步了解 Qt Creator 设计应用程序的基本过程,对使用 Qt Creator 编写 Qt C++ 应用程序建立初步的了解。

  单击 Qt Creator 的菜单项,出现如图 1 所示的对话框。在这个对话框里选择需要创建的项目或文件的模板。

  新建文件或项目对话框

  图 1 新建文件或项目对话框

  Qt Creator 可以创建多种项目,在最左侧的列表框中单击“Application”,中间的列表框中列出了可以创建的应用程序的模板,各类应用程序如下:

  Qt Widgets Application,支持桌面平台的有图形用户界面(Graphic User Interface,GUI) 界面的应用程序。GUI 的设计完全基于 C++ 语言,采用 Qt 提供的一套 C++ 类库。Qt Console Application,控制台应用程序,无 GUI 界面,一般用于学习 C/C++ 语言,只需要简单的输入输出操作时可创建此类项目。Qt Quick Application,创建可部署的 Qt Quick 2 应用程序。Qt Quick 是 Qt 支持的一套 GUI 开发架构,其界面设计采用 QML 语言,程序架构采用 C++ 语言。利用 Qt Quick 可以设计非常炫的用户界面,一般用于移动设备或嵌入式设备上无边框的应用程序的设计。Qt Quick Controls 2 Application,创建基于 Qt Quick Controls 2 组件的可部署的 Qt Quick 2 应用程序。Qt Quick Controls 2 组件只有 Qt 5.7 及以后版本才有。Qt Canvas 3D Application,创建 Qt Canvas 3D QML 项目,也是基于 QML 语言的界面设计,支持 3D 画布。 在图 1 显示的对话框中选择项目类型为 后,单击“Choose…”按钮,出现如图 2 所示的新建项目向导:

  新建项目向导第 1 步:项目名称和项目存储位置设置

  图 2 新建项目向导第 1 步:项目名称和项目存储位置设置

  在图 2 中,选择一个目录,如“E:QtDemo”,再设置项目名称为 Demo, 这样新建项目后,会在“E:QtDemo”目录下新建一个目录,项目所有文件保 存在目录“E:QtDemoDemo”下。

  在图 2 中设置好项目名称和保存路径后,单击“Next”按钮,出现如图 3 所示的选择编译工具的界面:

  img

  图 3 新建项目向导第 2 步:选择编译工具

  可以将这几个编译工具都选中,在编译项目时再选择一个作为当前使用的编译工具,这样可以编译生成不同版本的可执行程序。

  新建项目想到第 3 步:选择界面基类

  图 4 新建项目想到第 3 步:选择界面基类

  在图 3 显示的界面中单击“Next”按钮,出现如图 4 所示的界面。在此界面中选择需要创建界面的基类(base class)。有 3 种基类可以选择:

  QMainWindow 是主窗口类,主窗口具有主菜单栏、工具栏和状态栏,类似于一般的应用程序的主窗口;QWidget 是所有具有可视界面类的基类,选择 QWidget 创建的界面对各种界面组件都可以 支持;QDialog 是对话框类,可建立一个基于对话框的界面; 在此选择 作为基类,自动更改的各个文件名不用手动去修改。勾选“创建界面”复选框。这个选项如果勾选,就会由 Qt Creator 创建用户界面文件,否则,需要自己编程手工创建界面。初始学习,为了了解 Qt Creator 的设计功能,勾选此选项。

  然后单击“Next”按钮,出现一个页面,总结了需要创建的文件和文件保存目录,单击“完成”按钮就可以完成项目的创建。

  完成了以上新建项目的步骤后,在 Qt Creator 的左侧工具栏中单击“编辑”按钮,可显示如图 5 所示的窗口。

   项目管理与文件编辑界面

  图 5 项目管理与文件编辑界面

  窗口左侧有上下两个子窗口,上方的目录树显示了项目内文件的组织结构,显示当 前项目为 Demo。项目的名称构成目录树的一个根节点,Qt Creator 可以打开多个项目,但是只有一个活动项目,活动项目的项目名称节点用粗体字体表示。

  在项目名称节点下面,分组管理着项目内的各种源文件,几个文件及分组分别为以下几项:

  Demo.pro 是项目管理文件,包括一些对项目的设置项。Headers 分组,该节点下是项目内的所有头文件(.h),图 5 中所示项目有一个头文件 mainwindow.h,是主窗口类的头文件。Sources 分组:该节点下是项目内的所有 C++源文件(.cpp),图 5 中所示项目有两个 C++ 源文件,mainwindow.cpp 是主窗口类的实现文件,与 mainwindow.h 文件对应。main.cpp 是主函数文件,也是应用程序的入口。Forms 分组:该节点下是项目内的所有界面文件(.ui)。图 5 中所示项目有一个界面文件mainwindow.ui,是主窗口的界面文件。界面文件是文本文件,使用 XML 语言描述界面的组成。 左侧上下两个子窗口的显示内容可以通过其上方的一个下拉列表框进行选择,可以选择的显示内容包括项目、打开文档、书签、文件系统、类视图、大纲等。在图 5 中,上方的子窗口显示了项目的文件目录树,下方显示打开的文件列表。可以在下方选择显示类视图,这样下方则显示项目内所有的类的结构,便于程序浏览和快速切换到需要的代码位置。

  双击文件目录树中的文件mainwindow.ui,出现如图 6 所示的窗体设计界面:

  集成在 Qt Creator 中UI设计器

  图 6 集成在 Qt Creator 中UI设计器

  这个界面实际上是 Qt Creator 中集成的 Qt Designer。窗口左侧是分组的组件面板,中间是设计的窗体。在组件面板的 Display Widgets 分组里,将一个Label组件拖放到设计的窗体上面。双击刚刚放置的 Label 组件,可以编辑其文字内容,将文字内容更改为“Hello, World!”。还可以在窗口右下方的属性编辑器里编辑标签的 Font 属性,Point Size(点大小)更改为 12,勾选粗体。

  单击主窗口左侧工具栏上的“项目”按钮,出现如图 7 所示的项目编译设置界面。

  项目编译器选择和设置界面

  图 7 项目编译器选择和设置界面

  界面左侧一栏的“Build & Run”下面显示了本项目中可用的编译器工具,要使用哪一个编译器用于项目编译,单击其名称即可,选择的编译器名称会用粗体字表示。这里选择使用 MinGW 32bit 编译器。

  每个编译器又有 Build 和 Run 两个设置界面。在 Build 设置界面上,有一个“Shadow build” 复选框。如果勾选此项,编译后将在项目的同级目录下建立一个编译后的文件目录,目录名称包含编译器信息,这种方式一般用于使用不同编译器创建不同版本的可执行文件。如果不勾选此项,编译后将在项目的目录下建立“Debug”和“Release”子目录用于存放编译后的文件。

  在设计完 mainwindow.ui 文件,并设置好编译工具之后,就可以对项目进行编译、调试或运行。主窗口左侧工具栏下方有 4 个按钮,其功能见表 1。

  图标作用快捷键img弹出菜单选择编译工具和编译模式,如 Debug或 Release模式img直接运行程序,如果修改后未编译,会先进行编译。即使在程序中设置了断点,此方式运行的程序也无法调试。Ctrl+Rimg项目需要以Debug模式编译,点此按钮开始调试运行,可以在程序中设置断点。若是以 Release模式编译,点此按钮也无法进行调试。F5img编译当前项目Ctrl+B 首先对项目进行编译,没有错误后,再运行程序。程序运行的界面如图 8 所示。这就是一个标准的桌面应用程序,我们采用可视化的方式设计了一个窗口,并在上面显示了字符串“Hello, World!”。

  实例程序 Demo 运行时界面

  图 8 实例程序 Demo 运行时界面

  在 Qt Creator 中也可以对程序设置断点进行调试,但是必须以 Debug 模式编译,并以“Start Debugging”(快捷键 F5)方式运行程序。

  程序调试的方法与一般 IDE 工具类似,不再详述。注意,要在 Qt Creator 里调试 MSVC2015 编译的程序,必须安装 Windows 软件开发工具包 SDK。

  前面章节中,通过在 xxx.ui 文件中拖拽 Label 组件,设计出了一个显示 “Hello,World!” 的窗口,如下图所示:

  img

  图 1 简单的界面

  本节我们完全舍弃 xxx.ui 文件,亲手编写代码实现图 1 所示的界面。

  首先,打开 Qt Creator 并创建一个 Qt Widgets Application 项目,创建过程可以参考 《编写第一个Qt程序》一节。需要注意的是,我们要创建一个不带 xxx.ui 文件的项目,如下图所示:

  img

  图 2 创建不带 ui 文件的图形界面项目

  最终创建的项目结构如下图所示:

  img

  图 3 项目结构

  Demo.pro 是项目文件,文件中的内容可以手动修改,我们会在《Qt pro文件详解》一节中详细讲解,本节不需要修改此文件。接下来,我们逐一介绍 main.cpp、mainwindow.h 和 mainwindow.cpp 这 3 个文件。

  1) main.cpp main.cpp 是主函数文件,内部主要包含应用程序的入口函数,也就是 main() 函数。

  我们知道,C/C++ 程序中 main() 函数的语法格式是固定的:

  Qt 界面程序中的 main() 函数也有固定的格式:

  对于刚刚学习 Qt 的读者,暂时不用了解第 3 行和第 5 行代码的含义,只要记住:使用 Qt 框架编写带界面的应用程序,main() 函数中必须包含第 3 行和第 5 行代码,否则程序无法正常运行。

  双击图 3 所示的 main.cpp 文件,可以看到该文件包含的所有代码:

  除了第 6、8 行代码外,其它代码的含义分别是:

  1~2 行:由于 main() 函数中分别定义了 QApplication 和 MainWindow 类的对象,因此需要引入 mainwindows.h 和 QApplication 头文件。mainwindow.h 文件是我们自己创建的,引入时用双引号括起来;QApplication 是 Qt 提供给我们的,引入时用括起来。第 7 行:MainWindow 是自定义的类,继承自 QMainWindow 主窗口类,因此 MainWindow 也是一个主窗口类。w 是 MainWindow 类实例化出的对象,表示一个主窗口。第 8 行:默认情况下,Qt 提供的所有组件(控件、部件)都是隐藏的,不会自动显示。通过调用 MainWindow 类提供的 show() 方法,w 窗口就可以在程序运行后显示出来。 2) mainwindow.h和mainwindow.cpp 创建项目时,我们在图 2 所示的对话框中定义了一个继承自 QMainWindow 的主窗口类,并起名为 MianWindow,该类的定义部分位于 mainwindow.h 头文件中,实现部分位于 mainwindow.cpp 源文件中。

  双击图 3 所示的 mainwindow.h 和 mainwindow.cpp 文件,可以看到它们各自包含的代码:

  初始状态下,MainWindow 类由 Q_OBJECT、构造函数和析构函数组成,这里重点介绍一下 Q_OBJECT 和构造函数:

  Q_OBJECT:本质是一个已定义好的宏,所有需要“信号和槽”功能的组件都必须将 Q_OBJECT 作为 private 属性成员引入到类中。本节设计的界面程序不会用到“信号和槽”,因此可以删除 Q_OBJECT。有关信号和槽,我们会在《Qt信号和槽机制详解》一节详细介绍。带参的构造函数:QWidget 是所有组件的基类,借助 parent 指针,可以为当前窗口指定父窗口。例如图 1 中,QLabel 文本框位于主窗口中,主窗口就是它的父窗口。当父窗口被删除时,所有子窗口也会随之一起删除。当然也可以不指定父窗口,那么当前窗口就会作为一个独立的窗口,不会受到其它窗口的影响。 直接运行程序,会输出下图所示的界面:

  img

  图 4 空白主窗口

  图 4 看到的就是 main() 函数中创建的 w 主窗口。由于没有往 w 窗口中放置任何组件,所以 w 是一个空白窗口。

  我们尝试向 w 主窗口添加一个文本框,需要对 MainWindow 类进行修改。修改后的 MainWindow 类如下:

  和先前空的 MainWindow 类相比,做了如下修改:

  添加了一个 QLabel 类的指针对象,相应地要引入头文件;在构造函数中定义了一个 QLabel 类的文本框对象,通过调用它的带参构造函数,设置它的父对象为当前类的对象,同时设置 “Hello,World!” 为要显示的文本信息。 有关 QLabel 组件的用法,我们会在《Qt QLabel文本框的使用》一节详细讲解,这里不用深究具体的语法。

  再次运行程序,显示的窗口如下图所示:

  img

  图 5 带文本框的主窗口

  图 1 和图 5 是类似的,区别在于图 5 中的 “Hello, World!” 没有加粗,也没有调整它在主窗口中的位置,这些都可以通过编码实现,后续讲 QLabel 时会做详细介绍。

  图 5 中,“Hello,World!” 文本框的父窗口是主窗口,所以文本框位于主窗口中(位置默认在窗口的左上角),主窗口关闭时文本框也会随之关闭。

  由此,我们就成功设计了一个包含文本框的窗口,这也是我们编写的第一个 Qt 程序。

  Qt 是一个著名的 GUI 框架,用来开发和用户交互的图形界面。作为 GUI 框架,丰富的控件和灵活的事件机制是不可或缺的,Qt 在这一方面做得非常优秀。

  Qt 控件又称组件或者部件,指用户看到的所有可视化界面以及界面中的各个元素,比如按钮、文本框、输入框等。

  为了方便程序员开发,Qt 提供了很多现成的控件。打开某个带 ui 文件的 Qt Widgets Application 项目,ui 文件的 Widget Box 一栏展示了 Qt 提供的几乎所有控件:

  img

  图 1 Qt 提供的控件

  Qt 中的每个控件都由特定的类表示,每个控件类都包含一些常用的属性和方法,所有的控件类都直接或者间接继承自 QWidget 类。实际开发中,我们可以使用 Qt 提供的这些控件,也可以通过继承某个控件类的方式自定义一个新的控件。

  前面说过,Qt 中所有可视化的元素都称为控件,我们习惯将带有标题栏、关闭按钮的控件称为窗口。例如,下图展示了两种常用的窗口,实现它们的类分别是 QMainWindow 和 QDialog。

  img

  图 2 Qt 窗口

  QMainWindow 类生成的窗口自带菜单栏、工具栏和状态栏,中央区域还可以添加多个控件,常用来作为应用程序的主窗口;QDialog 类生成的窗口非常简单,没有菜单栏、工具栏和状态栏,但可以添加多个控件,常用来制作对话框。 除了 QMainWindow 和 QDialog 之外,还可以使用 QWidget 类,它的用法非常灵活,既可以用来制作窗口,也可以作为某个窗口上的控件。

  窗口很少单独使用,它的内部往往会包含很多控件。例如图 2 中,我们分别往 MainWindow 和 Dialog 窗口中放置了一个按钮控件,根据需要还可以放置更多的控件。当窗口弹出时,窗口包含的所有控件会一同出现;当窗口关闭时,窗口上的所有控件也会随之消失。

  实际开发中,制作应用程序的主窗口可以用 QMainWindow 或者 QWdiget;制作一个提示信息的对话框就用 QDialog 或 QWidget;如果暂时无法决定,后续可能作为窗口,也可能作为控件,就选择 QWidget。

  简单地理解,Qt 事件指的是应用程序和用户之间的交互过程,例如用户按下某个按钮,点击某个输入框等等。实际上除了用户会与应用程序进行交互外,操作系统也会与应用程序进行交互,例如当某个定时任务触发时,操作系统会关闭应用程序,这也是一个事件。

  《分析第一个Qt程序》一节中提到,Qt 界面程序的 main() 主函数中首先要创建一个 QApplication 类的对象,函数执行结束前还要调用 QApplication 对象的 exec() 函数。一个 Qt 界面程序要想接收事件,main() 函数中就必须调用 exec() 函数,它的功能就是使程序能够持续不断地接收各种事件。

  Qt 程序可以接收的事件种类有很多,例如鼠标点击事件、鼠标滚轮事件、键盘输入事件、定时事件等。每接收一个事件,Qt 会分派给相应的事件处理函数来处理。所谓事件处理函数,本质就是一个普通的类成员函数,以用户按下某个 QPushButton 按钮为例,Qt 会分派给 QPushButton 类中的 mousePressEvent() 函数处理。

  事件处理函数通常会完成两项任务,分别是:

  修改控件的某些属性,比如当用户按下按钮时,按钮的背景颜色会发生改变,从而提示用户已经成功地按下了按钮;运用信号和槽机制处理事件。 信号和槽是 Qt 中处理事件最常用的方法,我们会在《Qt信号和槽》一节中做详细地讲解。

  创建一个不带 ui 文件的 Qt Widgets Application 项目,项目中只保留一个 main.cpp 源文件,删除其它文件(mainwindows.h 和 mainwindow.cpp)。将下述代码直接拷贝到 main.cpp 文件:

  运行结果如下图所示:

  img

  图 3 运行结果

  整个程序的运行过程如下:

  先创建了一个 QWidget 窗口,在窗口上添加一个 QPushButton 按钮;当用户点击按钮时,Qt 会将此事件分派给 QPushButton 类的 mousePressEvent() 事件处理函数;mousePressEvent()函数内部会改变按钮的属性,提示用户成功按下了按钮,还会调用 clicked() 函数发出“用户点击按钮”的信号。对于发出的信号,程序中调用 connect() 函数指定 QWidget 类的 close() 函数接收 clicked() 信号,close() 函数会关闭 widget 窗口。 实际开发中,我们用各种 Qt 控件设计出功能丰富的界面,用 Qt 事件完成与用户的交互。学习 Qt 界面编程,本质上就是学习 Qt 各个控件的用法以及对 Qt 事件的处理。本节我们只是对 Qt 控件和事件做了简单的了解,接下来将为您系统地讲解它们的用法。

  信号和槽是 Qt 特有的消息传输机制,它能将相互独立的控件关联起来。

  举个简单的例子,按钮和窗口本是两个独立的控件,点击按钮并不会对窗口造成任何影响。通过信号和槽机制,我们可以将按钮和窗口关联起来,实现“点击按钮会使窗口关闭”的效果。

  在 Qt 中,用户和控件的每次交互过程称为一个事件,比如“用户点击按钮”是一个事件,“用户关闭窗口”也是一个事件。每个事件都会发出一个信号,例如用户点击按钮会发出“按钮被点击”的信号,用户关闭窗口会发出“窗口被关闭”的信号。

  Qt 中的所有控件都具有接收信号的能力,一个控件还可以接收多个不同的信号。对于接收到的每个信号,控件都会做出相应的响应动作。例如,按钮所在的窗口接收到“按钮被点击”的信号后,会做出“关闭自己”的响应动作;再比如输入框自己接收到“输入框被点击”的信号后,会做出“显示闪烁的光标,等待用户输入数据”的响应动作。在 Qt 中,对信号做出的响应动作就称为槽。

  img

  图 1 信号和槽

  信号和槽机制底层是通过函数间的相互调用实现的。每个信号都可以用函数来表示,称为信号函数;每个槽也可以用函数表示,称为槽函数。例如,“按钮被按下”这个信号可以用 clicked() 函数表示,“窗口关闭”这个槽可以用 close() 函数表示,信号和槽机制实现“点击按钮会关闭窗口”的功能,其实就是 clicked() 函数调用 close() 函数的效果。

  信号函数和槽函数通常位于某个类中,和普通的成员函数相比,它们的特别之处在于:

  信号函数用 signals 关键字修饰,槽函数用 public slots、protected slots 或者 private slots 修饰。signals 和 slots 是 Qt 在 C++ 的基础上扩展的关键字,专门用来指明信号函数和槽函数;信号函数只需要声明,不需要定义(实现),而槽函数需要定义(实现)。 为了提高程序员的开发效率,Qt 的各个控件类都提供了一些常用的信号函数和槽函数。例如 QPushButton 类提供了 4 个信号函数和 5 个 public slots 属性的槽函数,可以满足大部分场景的需要。

  实际开发中,可以使用 Qt 提供的信号函数和槽函数,也可以根据需要自定义信号函数和槽函数,我们会在《Qt自定义信号和槽函数》一节做详细介绍。

  Qt Creator 提供了很强大的 Qt GUI 开发手册,很容易就能查到某个控件类中包含哪些信号函数和槽函数。举个例子,查看 QPushButton 类中信号函数和槽函数的过程是:

  在程序中引入头文件,双击选中“QPushButton”并按 “Fn+F1” 快捷键,就会弹出 QPushButton 类的使用手册,如下图所示。 img

  图 2 QPushButton类的使用说明

  在 Contents 部分可以看到,QPushButton 类只提供了一些属性的槽函数,没有提供信号函数。对于 QPushButton 类按钮,除了可以使用自己类提供的槽函数,还可以使用从父类继承过来的信号函数和槽函数。由图 2 可知,QPushButton 的父类是 QAbstractButton,点击 QAbstractButton 就可以直接跳转到此类的使用手册,如下图所示: img

  图 3 QPushButton父类使用说明

  QAbstractButton 类中既有 Signals 信号函数,也有 Public Slots 槽函数,这里不再一一列举,感兴趣的读者可以自行查看。

  注意,并非所有的控件之间都能通过信号和槽关联起来,信号和槽机制只适用于满足以下条件的控件:

  控件类必须直接或者间接继承自 QObject 类。Qt 提供的控件类都满足这一条件,这里提供一张 Qt常用类的继承关系的高清图片,感兴趣的读者可以简单了解一下。控件类中必须包含 private 属性的 Q_OBJECT 宏。 将某个信号函数和某个槽函数关联起来,需要借助 QObject 类提供的 connect() 函数。

  connect() 是 QObject 类中的一个静态成员函数,专门用来关联指定的信号函数和槽函数。

  关联某个信号函数和槽函数,需要搞清楚以下 4 个问题:

  信号发送者是谁?哪个是信号函数?信号的接收者是谁?哪个是接收信号的槽函数? 仍以实现“按下按钮后窗口关闭”为例,先创建一个窗口和一个按钮,如下所示:

  信号发送者是 But 按钮对象,要发送的信号是“按钮被点击”,可以用 QPushButton 类提供的 clicked() 信号函数表示;信号的接收者是 widget 主窗口对象,“窗口关闭”作为信号对应的槽,可以用 QWidget 类提供的 close() 函数表示。

  在 Qt5 版本之前,connect() 函数最常用的语法格式是:

  QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)

  各个参数的含义分别是:

  sender:指定信号的发送者;signal:指定信号函数,信号函数必须用 SIGNAL() 宏括起来;reveiver:指定信号的接收者;method:指定接收信号的槽函数,槽函数必须用 SLOT() 宏括起来;type 用于指定关联方式,默认的关联方式为 Qt::AutoConnection,通常不需要手动设定。 用 connect() 函数将 But 按钮的 clicked() 信号函数和 widget 窗口的 close() 槽函数关联起来,实现代码如下:

  如此就实现了“按下按钮会关闭窗口”的功能。

  Qt5 版本中,connect() 函数引入了新的用法,常用的语法格式是:

  QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::Con

上一篇:写给成年人心酸短句
下一篇:杨洋王楚然扫楼引争议,杨洋举止耐人寻味,王楚然令人心疼!