目录
1.创建项目的说明
2.代码介绍说明
2.1文件分类介绍
2.2sources文件
2.3widget.ui文件
2.4widget.h文件
2.5中间文件
2.6.pro文件
3.打印输出hello world
3.1图形化界面生成控件
3.2代码生成控件
3.3打印结果展示
4.对于内存泄露的讨论
4.1对象树
4.2与栈开辟空间的对比
4.3展示对象树释放对象的过程
4.4自定义类的设计
4.5我的总结
5.乱码问题的解释
5.1对于字符编码方式认识
5.2qDebug认识
5.3修改运行
1.创建项目的说明
之前的这个教程里面已经介绍了这个qt里面的项目的创建过程以及创建出来的这个代码的一些说明
我们当时进行这个项目的创建的时候,这个里面的默认的这个配置(information即下面的这个配置页面),这个里面的默认的选项是windows之类的,我们这个时候点击下拉框,把这个改成wight这个选项,我们前期都是使用的这个选项进行项目的创建;
2.代码介绍说明
2.1文件分类介绍
在一个简单生成的这个qt项目文件里面,其实这个里面的文件的内容还是蛮多的,我们只需要大致了解即可,很多文件是自动生成创建的,需要我们手动写的代码还是在一些主要的文件里面;
除了这个主要的文件之外,其他的这个文件就是自动生成创建的,了解即可;
2.2sources文件
- 我们的这个示例代码就是包含了;两个头文件,使用这个main函数进行程序的编写,qapplication就是使用这个已知的类去创建一个对象a,这个其实就是执行的构造函数,argc和argv就是我们的这个命令行参数;
- widgit就是创建一个对象w,w其实就是一个控件对象,show函数的调用就是让这个控件给显示出来
- return里面的这个方法的调用目的就是让这个程序运行起来即可;
2.3widget.ui文件
这个文件我们双击之后就会跳转到下面的这个页面:这个是qt designer的页面,这个是一个图形化的页面,左边的是qt里面的内置的空间,直接拖拽控件就可以进行创建项目界面
我们在重新回到这个ui文件,就可以看到下面的这个代码的格式,这个其实就是xml类型的代码,和我们熟悉的这个html世纪上是很相似的,这个里面也有这个标签之类的定义,这个xml实际上就是为了把我们的这个文件生成c++代码,从而进一步把这个完整的界面构造出来;
2.4widget.h文件
这个文件里面的内容就是我们对于这个widget的相关的声明;
上面的这个ifndef这些就是保证我们的头文件只包含一次,建议使用#pragme once让这个文件只会包含一次;
这个代码里面也可以看出来,这个widget继承自父类Qwidget,这个父类是内置的,想要使用就要包含对应的头文件,这个里面的第四行代码就是为了包含这个对应的头文件;但是也不是所有的情况下都需要包含头文件,可能需要间接包含也是可以被允许的;
上面这个代码里面的14行里面的这个东西实际上是我们的qt里面的一个宏,qt里面有一个很重要的机制:信号和槽,需要使用这个机制的时候就需要包含这个宏,这个宏和信号槽有关联;
最下面的就是这个构造函数和析构函数的调用过程,15行的这个括号里面的参数是qt里面的对象数机制,用来表明我们的这个对象数是谁;
2.5中间文件
这个文件夹路径里面会有这个我们自己创建的项目文件,上面的两个文件就是我们的这个中间文件
具体的内容就是一些生成的这个临时文件,里面的这个makefile文件是自动生成的,不需要我们自己去手写文件;
这个里面的exe就是可执行程序,和我们点击qt里面的这个运行按钮看到的效果是一样的;
2.6.pro文件
第一行就是引入一些模块,我们后面如果有需要也是可以进行修改的;
18-20就是描述编译器需要进行编译的文件有哪些,这个我们不需要管;
pro文件类似于我们的这个makefile文件,指明了这个编译的方法,进行编译的文件和编译之后生成的文件,qt creater把这个编译的细节都封装好了,我们直接点击这个运行按钮就可以了;
3.打印输出hello world
如何打印输出hello world这个内容,基本上是我们在学习所有的编程语言入门的时候都会经历的一个环节,这个qt的学习也不会例外,下面我们会介绍在qt creater里面打印这个hello world的两个方式,本质都是生成控件,一个是使用的图形化界面的方式生成控件,还有一个就是通过代码生成这个控件;
3.1图形化界面生成控件
进入这个qt designer里面:在这个窗口里面点击ui文件就会跳转到我们的这个designer里面去;
在这个里面,我们使用图形化界面的方式生成这个效果,就需要使用这个label标签,我们把这个拖到这个幕布上面去,就是点击这个label拖到这个画布上面,拖动过去之后的大小其实是可以进行修改的,我们通过拉拽的方式就可以对于这个拖动之后的这个标签的大小进行放大或者是缩小;
然后双击这个标签,就可以对于这个内容进行修改,我们就可以把这个hello world内容写到这个画布上面去,点击运行,这个时候会提示我们是否保存修改,我们直接点击save all即可,就是保存所有的修改的意思;
和之前的图形化页面相比较,我们就会发现这个ui文件里面的这个xml内容实际上就多了我们写了这个hello world的相关的配置内容;
3.2代码生成控件
这个时候我们不可以直接创建,而是把上面的那个使用图形化界面生成控件的项目关闭掉,之后再去创建新的文件来编写我们的代码生成控件;
下面的这个就是我们的代码,就是主要在widget.cpp文件里面操作的,主要是在这个cpp文件里面的构造函数中添加内容,下面我将对于代码进行详细说明:
- 我们需要使用new方法创建一个对象出来,这个对象我们命名为label,且它的类型是QLabel*类型的;
- 这个QLabel类型的使用需要包含对应的头文件,即include<Qlabel>这个里面在包含的时候会 有Qlabel.h文件的提示,这个我在注释里面进行了说明,实际上就是当时的c++不是很完善,qt自己设计了一套方法使用,保证不会出问题;
- 这个new对象的时候,里面的参数需要加上这个this,这个原有的代码里面也是有这个this的;
- label->setText就是显示控件里面的文本的内容,对应的方法参数就是我们的内容hello world;
- setText函数参数实际上是一个Qstring类型的对象,这个我们可以像下面一样隐式的写,也可以写做这个Qstring("hello world")进行表示,就算我们直接写,qt也是可以自动进行转换的;
3.3打印结果展示
打印结果显示:下面的这个使用代码生成的是直接把这个显示在我们的左上角,如果是使用label拖拽的方式的话,就是显示在我们的拖拽的那个位置,这个是可以进行修改的;
4.对于内存泄露的讨论
4.1对象树
可能细心的同学已经看到了这个问题,就是内存泄露的问题,我们上面使用这个new创建对象,但是却没进行delete操作,按理说就存在内存泄露的风险,但是这个运行的时候没有遇到问题,这个其实就是因为我们把这个对象挂到了对象树上面去;
下面的这个就是一个简单的对象树,这个对象树最主要的作用就是为了能够在合适的时机,把我们自己创建的对象统一释放掉,对象树管理这些对象,因此这个时候没有出现内存泄漏的问题;
4.2与栈开辟空间的对比
我们上面的这个是使用的new开辟空间的,这个也可以直接在栈上面开空间,即QLabel label进行对象的创建,这个时候我们的label就不是一个指针了,因此我们需要使用这个label.setText进行这个函数的调用,这个时候依然是可以运行的,但是没有这个结果的打印输出;
这个就是因为我们在栈上面开空间的时候,我们的创建的对象就不是交给对象树进行管理的,因此这个时候对于对象的释放就出现了问题,这个时候的打印结果无法正常输出,这个也是我们为什么使用new创建对象的原因;
4.3展示对象树释放对象的过程
我们上面是自己创建的这个label对象,我们想要看到这个对象树释放对象的过程,就需要我们自己独立去实现一个类,看看会不会调用这个里面的析构函数;
就是我们原来是使用的系统的类创建对象,现在我们自己实现这个过程,看看会不会达到相同的效果;
在qt creater里面,我们自己如何创建一个类呢,按照下面的这个过程尝试一下吧:这个也会加深我们对于内存泄漏的理解深度~~
首先点击这个工具栏的文件里面的新建文件:
选择这个c++文件,右边就为我们默认匹配这个c++ class文件,直接创建:
这个时候,我们需要填写这个类的名字,因为我们的这个类是自己创建的,我们就可以取名字为mylabel,下面让我们选择这个base class也就是基础类,实际上就是我们自定义的这个类的父类,我们选择这个QLlabel(就是之前包含的那个头文件,这个是系统自带的),注意这个QLabel里面的这个前面的两个字符都是大写的,这个一定不要搞错了;
我们选择的时候发现没有,这个时候我们就在第三个框框里面去自己写上去就可以了,这个里面还为我们用户提供了一些头文件,我们不用管就好了,就算用到了,我们自己也是可以手动包含的;
接下来的这个就是确认我们的文件的生成的位置,这个也是选择默认的就行,直接点击完成:
完成之后我们就会发现这个文件目录里面多了我们自己创建的这个mylabel的.h文件和.cpp文件,这个就表明我们上面的创建的过程是成功的;
4.4自定义类的设计
对于新的.h文件的修改:可以在这个构造函数里面添加上我们的parent,是QWidget*类型的,这样做的目的就是把新创建的对象添加到这个对象树上面去,因为我们的这个父类在对象树上面,我们的自定义类继承自这个父类,就可以挂在这个对象树上面了;
下面的这个是在.cpp文件里面的修改的过程,我们可以使用这个F4直接切换到这个.h对应的这个.cpp文件里面去,比较迅速~~
mylabel就是我们自己创建的一个类,继承自父类parent,是QWidget*类型的父类,这几个类型之间的关系一定要捋清楚了;Qlabel是系统的这个自带的类,我们实现的就是一个类似的这个功能,只不过是我们自己定义的,因此取名字为mylabel;
接下来,我们就是在这个mylabel里面添加上这个析构函数,打印输出一句话:
上面进行的操作,都是在创建类,我们还没进行对象的创建,我们需要在这个widget文件里面进行这个对象的创建工作;创建的方法就是用的new,和上面没有什么区别;
这个时候保存所有文件,点击运行,这个时候打印了这个hello world,怎么看到这个析构函数执行时候的日志的输出文件呢,实际上,我们可以使用这个找到这个下面的应用程序输出,这个时候,我们把这个hello world输出的这个框框叉掉,这个时候我们的日志就会被打印出来了;
但是这个里面出现了乱码,我们下面会介绍一下这个解决方案;
4.5我的总结
其实对于这个自定义类和对象的这个过程,对于初学者而言肯定是有些许复杂的,不同文件之间的切换以及这个构造函数,析构函数,继承关系的调整都是我们需要注意的;
首先,我们的这个QLabel是系统自带的,我们想要看看自己实现一个类似于这个QLabel会不会执行这个析构函数,因为我们使用这个QLabel创建对象的时候,这个析构函数的执行过程我们是看不到的,我们想要确认一下这个析构函数的执行的过程,因此我们自己定义了一个mylabel的类,这个类继承自QWidget*类型的 parent的父类,这个是我们的整体逻辑和思路;
接下来才是去写使用我们自定义的类创建对象,然后去写这个析构函数,打印输出日志等操作;
5.乱码问题的解释
5.1对于字符编码方式认识
我们目前的主流的编码方式就是GBK和utf-8,我们的这个文件里面的这个代码的编码方式就是utf-8,但是这个qt creater里面的这个终端的编码方式和utf-8不同,因此出现了这个乱码的情况;
5.2qDebug认识
我们上面是使用的这个cout打印输出的,出现了这个乱码的问题,我们使用这个qt里面自带的这个qdebug进行打印就可以让这个系统自动调整编码的相关设置,帮助我们解决乱码的问题;
5.3修改运行
加上这个头文件,使用这个qdebug()打印输出这个调试的日志,就可以解决这个乱码的问题;
qdebug可以通过设置开关,实现对于这个发布和调试过程中是否有这个日志的控制,是有好处的~