当我们安装了Qt Creater后,我们创建一个新项目。
Build System为选择构建工具。Qt框架会在编译时自动先调用一系列的生成工具,基于我们写的代码生成一系列其它的C++代码,然后最后将这些代码进行编译。qmake是老牌的Qt构建工具了,CMake并非是Qt专属的构建工具,很多其它项目也会使用CMake构建。Qbs为Qt新一代的构建工具。我们选择qmake即可。
Translation File为Qt国际化相关的内容,在这里可以选择翻译文件,我们现在暂时不关注。
Kits为选择编译器,即选择一下基于哪个编译器的Qt SDK来构建后续代码。MinGw 就是Qt SDK中内置的编译器,就类似于windows版本的gcc/g++编译器。
Summary为选择版本控制工具。
然后我们点击运行按钮,就可以将一个初始化的Qt项目运行起来。因为我们此时还没有向窗口中插入任何内容,所以此时只显示了一个空窗口。需要注意的是我们创建的Qt项目的路径中不能包含中文。
下面我们来看这个最简单的Qt项目中的一些文件。
main.cpp文件。
mainwindow.h文件。
mainwindow.cpp文件。
mainwindow.ui文件。
.pro文件的作用就类似于我们在Linux中学过的Makefile文件,只不过.pro文件和Makefile文件的语法不一样。qmake搭配.pro起到的作用就和Makefile的作用类似。
Qt项目在运行时生成的中间文件。我们上面看到的.h .cpp .pro 和 .ui文件都是项目的源代码,如果我们编译运行Qt项目的话,构建过程中还会生成一些中间文件。我们可以查看中间文件都有哪些。
在运行一次Qt项目后,就会在项目目录并列的地方多出来一个 “build-xxxx” 的目录,这个目录里面就是该项目运行过程中,生成的一些临时文件。
通过Qt Designer设计的界面的具体细节的实现都在setupUi方法中。
debug和release目录下的.exe文件就是项目最终生成的可执行程序,如果直接运行,效果就和之前在Qt Creator中运行时的效果相同。
可以通过两种方式实现hello world。
下面为使用图形化的方式。我们看到当使用Qt Designer设计界面时,对应的ui文件的xml中的代码也会跟着改变,这些都是Qt Creator自动完成的。
下面我们通过纯代码的方式。一般通过代码来构造界面的时候,通常会把构造界面的代码放到Widget/MainWindow的构造函数中。
因为我们使用了QLabel,所以我们要包含对应的头文件。
我们看到当包含头文件时,有两种形式的头文件。Qt为1991年推出的,当时C++标准还没有成立,所以Qt使用了自己的这种qlabel.h风格的头文件。当1998年之后,C++标准成立了,C++98标准规定了新的头文件风格,统一使用#include< cstdio >代替c语言中的#include< stdio.h >,Qt为了响应C++98的标准,所以就推出了一套QLabel的头文件包含风格。
创建QLabel对象时,可以在堆上创建,也可以在栈上创建,但是我们更推荐在堆上创建,因为Qt中有一个对象树的概念,在堆上创建的对象可以通过对象树来进行销毁。
当我们通过setText函数来设置label对象要显示的文本时,看到setText函数的参数为一个QString引用。这个QString类型和C++中的String类型有什么区别呢?
我们知道Qt诞生于1991年,当时C++98标准还没有形成,当时在Qt中表示字符串可以使用c语言风格的字符串(\0结尾),也可以使用C++的string类型,但是当时C++的string类型并不好用,所以Qt为了让自己的开发能变得高效,就自己开发了一套轮子,即Qt中的字符串QString,动态数据QVector,链表QList,字典QMap等。虽然现在C++的标准已经形成了,但是Qt不可能舍弃掉自己包装好的容器类,所以Qt中的接口都支持自己包装好的容器,不过也支持C++中的容器。在Qt中QString和std::string的转换也很方便,其实在Qt中使用QString比使用std::string好一点,因为QString内部已经对字符编码做了处理了,而不像std::string没有做处理。
QString中也提供了c语言风格字符串作为参数的构造函数。
在 Qt 中创建很多对象的时候会提供?个 Parent 对象指针,下?来解释这个 parent 到底是?什么的。
这种机制在 GUI 程序设计中相当有?。例如,?个按钮有?个 QShortcut(快捷键)对象作为其?对象。当删除按钮的时候,这个快捷键理应被删除。这是合理的。
QWidget 是能够在屏幕上显?的?切组件的?类。
Qt 引?对象树的概念,在?定程度上解决了内存问题。
Qt对象树如图:
下面我们自定义一个MyLabel控件来验证对象树对子对象的自动释放。
然后我们实现MyLabel的析构函数。
小技巧,我们在写完一个函数的声明之后,按下alt+enter,就可以自动在对应的cpp文件中添加函数的定义了。
然后我们在Widget中添加一个MyLabel控件。
当我们执行项目时,我们看到在Widget窗口中的MyLabel正常显示出来内容了。
当我们关闭Widget窗口时,此时我们在代码中并没有delete label,但是我们看到还是调用了MyLabel的析构函数,这就是Qt中的对象树自动释放了子对象。但是我们看到打印的消息中,汉字被显示为了乱码,这其实是因为编码方式不匹配造成的。
我们知道计算机中只能存储二进制的数据,我们平常看到的英文字母在计算机中存储的其实是它的ASCII码值,即ASCII码为每一个字符都规定了一个对应的数字来表示,所以计算机中存储这一个数字就表示ASCII码对应的字母。我们知道英文字母是有限的26个,如果加上我们常用的+、-、*、#等等这些字符,使用一个字节就足够存储了,这就是ASCII码。
但是我们的汉字是很多的,日常使用的汉字大概是4K多个,但是算上各种生僻字,总数差不多有6w左右,那么我们存储汉字也需要采用一个汉字和数字对应的表来存储。即使用一个大表格,这个表格需要可以表示6
w以上的数,然后我们给每个汉字分配一个整数即可。但是具体这个表格是什么样的,具体每个汉字使用哪一个数字来表示,这个就不一定了。因为每一套字符集对于同一个汉字都有不同的数字表示,并且每一套字符集的转码和解码方式也不同。
目前汉字字符集主要有两种表示方式:
乱码问题出现的原因就是因为编码方式不匹配,例如我们的字符串本身是utf8编码的,但是在终端显示时是按照GBK的方式来解析显示的,那么此时就会出现乱码。即拿着utf8的数值去查询gbk的码表,此时就会出现乱码。
在mylabel.cpp中字符串使用的哪种方式编码和当前mylabel.cpp文件的编码方式是一致的。
我们可以找到mylabel.cpp这个源代码文件,然后通过记事本打开,点击另存为,在下面就可以看到mylabel.cpp文件的编码方式。我们看到mylabel.cpp文件的编码方式为utf8,而在Qt Creator内置的终端中,可能不是使用utf8的方式来显示字符串的,所以就出现了乱码。
那么我们应该怎么解决这个乱码问题呢?在Qt中自己封装的QString容器是可以帮助我们自动的处理编码方式的,而且不只是QString,Qt也提供了专门用来打印日志的工具,也能自动处理编码方式。Qt中提供了qDebug()工具,借助这个就可以完成打印日志的过程,很好的处理字符编码。
qDebug()其实是个宏,这个宏封装了QDebug对象,直接使用qDebug()就相当于使用cout了。后面我们在Qt中,如果向通过打印日志的方式输出一些调试信息,都可以优先使用qDebug(),因为qDebug()对编码进行了处理,并且qDebug()可以通过编译开关来实现一键式关闭。