本文为文献 1的阅读笔记,主要记录自己不太熟悉的内容,补充知识盲区。个人对这个资料的初步印象不错,先学习一下。这本教程针对 Qt5,且假设读者有一定的Qt基础。
终极建议:如果有时间,而且英文能力可以,直接阅读英文文档是最好的:首页或者文档。资料很多,我暂时也没细看,需要时候要仔细研究。
1. 认识Qt
Qt 虽然经常被当做一个 GUI 库,用来开发图形界面应用程序,但这并不是 Qt 的全部;Qt 除了可以绘制漂亮的界面(包括控件、布局、交互),还包含很多其它功能,比如多线程、访问数据库、图像处理、音频视频处理、网络通信、文件操作等,这些 Qt 都已经内置了。Qt 是应用程序开发的一站式解决方案!除了与计算机底层结合特别紧密的应用,大部分应用程序都可以使用 Qt 实现。
1.1. Qt的安装目录
Qt Creator的安装参考这篇文章。
以Qt 5.9.0 为例,其安装目录为:
- Qt/5.9和Qt/Tools文件夹下都有…/mingw53_32目录,但是Qt/5.9下是Qt用mingw53_32编译的库,Qt/Tools下则是mingw53_32工具集本身,例如编译器 g++、链接器 ld、make 工具、打包工具 ar 等。
- 5.9版本的QtCreator 使用 MSVC2015 编译生成,所以安装目录里有一个 vcredist 文件夹存储 VC 运行库安装文件。
- MaintenanceTool.exe ,对于离线安装包,它只能用于删除软件包,如果 Qt 开发环境是用在线方式安装的,这个工具还可以管理开发环境组件和升级组件。
- Qt 类库的帮助文件位于 Qt/Docs 文件夹里,可以用 Qt Assistant 工具查看,直接打开html页面查看也可以。
Qt类库是Qt的核心,位于Qt/5.9文件夹下,Qt/5.9文件夹下的每个子文件夹对应一种运行平台/编译平台,例如mingw,msvc,arm等,用mingw举例,其目录结构为:
在Qt类库中,以xxxd.a/xxxd.dll格式的文件是用于debug编译的库文件,而xxx.a/xxx.dll则是用于release的,例如libQt5Guid.a/Qt5Guid.dll,libQt5Gui.a/Qt5Gui.dll。
1.2. Qt自身的开发工具链
Qt 不是凭空产生的,它是基于现有工具链打造而成的,它所使用的编译器、链接器、调试器等都不是自己的,Qt 官方只是开发了上层工具。
Qt 使用的工具链主要有:GNU(各种软件在linux位于/usr/bin/ 目录,如gcc、g++、ld、ar、make、gbd、ldd[查看可执行文件依赖的共享库])、MinGW(Windows下的GNU工具链,使用Dependency Walker查看可执行文件依赖的共享库)、CMake(跨平台的)、Qt工具集(qmake等,具体如下图)。
1.3. 命令行开发
Qt SDK 提供了一个命令行环境, 给那些有特殊需求的开发者, 方便他们在不使用 Qt Creator 集成开发环境的情况下编译应用程序。我们可以从如下地方找到命令行程序:
在该命令窗口中,可以运行qmake, qmlsecne等命令。
qmlscene是随着Qt 5发布的 一个工具, 用来加载 QML 文档, 它使得我们可以在应用开发过程中随时查看 QML 代码的效果。这是一个在应用程序完成之前加载和显示QML文档的实用程序。使用qmlscene就可以查看.qml文件的效果了(这里暂时不研究如何使用)。
下面举例说明如何命令行编译:
①创建一个工程文件夹,在其下面编辑.cpp.h.pro.qml.qrc等文件,注意要保存为utf8格式。这里我们只创建一个main.cpp文件:
②打开上图所示的qt命令行终端Qt 5.10.1 for Desktop (MinGW 5.3.0 32 bit)【这是我自己的版本,根据安装版本名称略有区别】,然后cd进我们的工程文件夹。
③逐步编译:
首先输入以下命令创建.pro文件:
qmake -project
然后打开.pro文件,在INCLUDEPATH…行之下添加如下一行(QT5的要求):
greaterThan(QT_MAJOR_VERSION, 4): QT +=widgets
然后,输入以下命令,会生成Makefile文件:
qmake
最后,我们运行以下两句进行编译,编译好的程序就存储在debug和release文件夹下了,我们就可以运行了:
mingw32-make -f Makefile.Debug
mingw32-make -f Makefile.Release
1.4. Qt Creator的使用技巧
1.4.1. 快捷键
1.4.2. 善用Qt帮助
帮助有下图所示的四种使用模式。
1.5. 一些细碎的知识
动静态库:Linux/Unix 系统里静态库扩展名一般是 .a,动态库扩展名一般是 .so 。Windows 系统里 VC 编译器用的静态库扩展名一般是 .lib,动态库扩展名一般是 .dll 。MinGW 使用的静态库扩展名为 .a ,而其动态库扩展名则为 .dll。
显式链接与隐式链接:这两种都是动态链接库的使用方式,默认是隐式的,即在链接生成可执行程序时就确立依赖关系,在该程序启动时,操作系统自动会检查它依赖的动态库,并一一加载到该程序的内存空间,在VC环境下,链接时使用动态库对应的 .lib 文件(包含动态库的导出函数声明,但没有实际功能代码),MinGW 是将动态库的导出函数声明放在了 .a 文件里;显式则表现为在程序中直接调用操作系统提供的函数,在必要的位置再加载动态库,Linux 里用 dlopen 函数打开并加载动态库,Windows 里一般用 LoadLibrary 打开并加载动态库。因此,Windows下无论是动态链接还是静态链接,一般都需要.lib/.a文件。
Linux下的图形界面KDE(GNOME是另外一种)就是Qt开发的:KDE 桌面系统已经将 Qt 作为默认的 GUI 库,Gnome 桌面系统则将 GTK+ 作为默认的 GUI 库。
windows下采用MSVC工具集的调试问题:
只安装Visual Studio的话是没有调试工具的,需要安装Windows Software Development Kit (SDK)补充。
Qt支持的项目类型:图形界面程序、控制台程序、Qt提供的一套基于QML的开发框架程序(界面效果酷炫)。
使build文件夹位于项目目录下的办法:将Shadow build勾选去掉即可:
Qt的可以使用VS开发,且也能调用Designer绘制界面,可参考(VS中使用Qt方法详解)。
2. Qt项目结构
这里用一个Qt Widgets Application\QMainWindow的项目举例,文件名任意,类名采用默认名称MainWindow。
打开Qt Creator,点击New Project创建项目,注意选择Qt Widgets Application\QMainWindow的配置。
2.1. 项目管理文件.pro
模块支持
Qt 类库以模块的形式组织各种功能,根据项目涉及的功能需求,在项目中添加适当的类库模块支持。使用 “QT += 模块名” 的形式即可加入该模块,例如:
QT += core gui # 添加图形界面模块
QT += sql # 添加数据库模块
Qt版本控制
greaterThan(Qt_MAJOR_VERSION, 4): Qt += widgets # 如果大版本号大于4,则增添widgets模块
可执行文件名设置
TARGET = 可执行文件名
项目模板设置
TEMPLATE = app # 表示项目使用的模板是 app,是一般的应用程序
# 此外还可以设置为lib,vcapp等
文件管理
SOURCES、HEADERS、FORMS分别对应程序中的源文件,头文件,和ui文件,一般是Qt Creator自动修改的。例如:
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
Qt工具链控制 - 总体控制
CONFIG += console # 允许控制台输出
CONFIG += c++11 # 支持C++11
Qt工具链控制 - 细节控制
DEFINES += QT_DEPRECATED_WARNINGS # 忽略未来废除这类警告,DEFINES用来对Qt工具链的工作进行指示。
添加额外的库
INCLUDEPATH += 额外库头文件目录绝对路径
LIBS += 额外库二进制文件路径
pro更具体的配置介绍,可以参考这篇博文。
或者官方文档关于pro文件的部分。
2.2. 界面文件.ui
在Qt Creator中双击ui文件自动进入可视化ui设计器。
属性编辑器
一般位于右下角位置。最大的组别实际表示的是继承关系,例如一个QPushButton,其父类是QAbstractButton,再上一层父类是QWidget,最上层是QObject。
动作与信号/槽编辑器
信号和槽的概念参考这里。
一般在中心最下方。这东西很好用,要灵活使用。
ui的实现机理浅析
绘制好界面后,编译程序,会发现多出了一个ui_xxx.h的文件,其中xxx是类名的全小写。在这个例子中,此时共有四个文件:
mainwindow.h
mainwindow.cpp
mainwindow.ui
ui_mainwindow.h # 自动生成的
我们根据这四个文件中的关键代码分析ui大致的实现原理(其实主要还是依赖Qt的工具链uic、moc等,一般了解即可):
对于控件接收的内置槽函数,程序中不会出现显式的connect过程,这实际上是由于ui_xxx.h文件中,setupUi函数最后的connectSlotsByName函数的作用。connectSlotsByName函数将搜索界面上的所有组件,将与槽函数匹配的信号和槽关联起来,它假设槽函数的名称是:
void on_<发出信号的控件名>_<信号名>(<signal parameters>);
如果接收信号的是窗体而不是窗体上的控件,那么则会在setupUi函数的connectSlotsByName函数之前自动添加connect函数。
而如果是自定义槽函数,则需要手动使用connect函数,规则为:
connect(发出信号的控件指针, SINGAL(信号函数名), 接收信号的widget指针, SLOT(槽函数名));
2.3. 信号与槽
关于信号与槽机制,需要注意的有:
①connect() 是 QObject 类的一个静态函数,QObject 是几乎所有 Qt 类的基类;
②一个信号可以连接多个槽;
③多个信号可以连接同一个槽;
④一个信号可以连接另外一个信号,例如:
connect(spinNum, SIGNAL(valueChanged(int)), this, SIGNAL (refreshInfo(int));
⑤严格的情况下,信号与槽的参数个数和类型需要一致;
⑥在使用信号与槽的类中,必须在类的定义中加入宏 Q_OBJECT;
⑦当一个信号被发射时,与其关联的槽函数通常被立即执行。
2.4. Resource
Qt添加资源文件的方法。
①在Qt编辑\项目面板中,右键项目名称,选择添加新文件,然后选择Qt Resource File,这样我们发现多出了一个Resources文件夹和一个qrc文件(我们自己起的名字)。
②右键qrc文件,选择Open In Editor,即可进入编辑页面。资源是按照树状结构管理的,只能有一级目录。页面下侧为编辑区域:
点击<添加>,发现弹出菜单有两个选项,分别是添加前缀和添加文件,我们需要先添加一个前缀,相当于文件夹;然后我们就可以添加资源进来了:
上图中即显示了我添加好的前缀icons。实际上,添加的前缀和文件会在上面的文件区域显示,我们从文件区域点击前缀名称,会发现下面的编辑区域跟着变化了,点击文件的效果也是类似的,这样我们就可以添加文件到已经创建好的几个前缀中,而且可以使用删除按钮删掉资源。
2.5. Action
Qt 使用QAction类作为动作,QAction包含了图标、菜单文字、快捷键、状态栏文字、浮动帮助等信息,Qt自己选择使用哪个属性来显示,无需我们关心。同时,Qt 能够保证把QAction对象添加到不同的菜单、工具栏时,显示内容是同步的。也就是说,如果我们在菜单中修改了QAction的图标,那么在工具栏上面这个QAction所对应的按钮的图标也会同步修改。
实际上,action主要就是菜单栏和工具栏的功能。具体操作过程如下:
①添加菜单(对于带有菜单的wight类型,例如QMainWindow):
点击这里的<在这里输入>,即可添加menu以及菜单栏action,添加后发现下发action编辑区出现对应的action。