目录
1.Qt命名规范2.Qt窗口坐标体系3.Qt文件4.容器:QT VS STL5.基类6.认识对象模型(对象树)1.是什么?2.解决内存问题1.如何解决?2.如何做? 3.举例说明4.总结 7.Qt父子对象8.Qt中乱码的处理9.注意 && 提要
1.Qt命名规范
类名:⾸字⺟⼤写,单词和单词之间⾸字⺟⼤写函数名及变量名:⾸字⺟⼩写,单词和单词之间⾸字⺟⼤写2.Qt窗口坐标体系
坐标体系:以左上⻆为原点 ( 0 , 0 ) (0,0) (0,0),X向右增加,Y向下增加
对于嵌套窗⼝/控件,其坐标是相对于⽗窗⼝/控件来说的
3.Qt文件
Qt系统提供的标准类名声明头⽂件没有.h
后缀Qt⼀个类对应⼀个头⽂件,类名就是头⽂件名QApplication
为应⽤程序类,一个程序有且仅有一个 QApplication
管理图形⽤⼾界⾯应⽤程序的控制流和主要设置QApplication
是Qt的整个后台管理的命脉,它包含: 主事件循环,在其中来⾃窗⼝系统和其它资源的所有事件处理和调度它也处理应⽤程序的初始化和结束,并且提供对话管理 对于任何⼀个使⽤Qt的图形⽤⼾界⾯应⽤程序,都正好存在⼀个QApplication
对象,⽽不论这个应⽤程序在同⼀时间内是不是有0、1、2或更多个窗⼝ 4.容器:QT VS STL
Qt在早些年为了开发顺畅,自己造轮子搞了一系列的基础类,来支持Qt开发 例如:QString, QVector, QList, QMap
但是现如今的STL和QT的基础类都打磨的很好了,所以在进行Qt开发的时候,如果需要用到上述容器类,可以使用STL容器,也可以使用Qt自己搞得这一套容器 但是Qt原生的API中,涉及到的接口,用的都是Qt自己的这一套容器 后续代码中,还经常会见到QString
这样的一些东西,而很少见到std::string
注意:QString
和std::string
之间能很方便的相互转换 实际上,QString
用起来要比std::string
香一些 因为QString
内部已经对于字符编码做了处理,而std::string
啥都没干 5.基类
QObject
是Qt内置的⽗类.Qt中提供的很多类都是直接或者间接继承⾃QObject
对于基类的选择,⽬前有三种基类
基类 | 说明 |
---|---|
QMainWindow | 主窗⼝类,⼀般⽤于较为复杂的应⽤程序,除了中央客⼾区界⾯,还包括菜单栏、⼯具栏、 状态栏以及多个可停靠的⼯具对话框等 |
QWidget | 最简单、最基本的窗体程序,⾥⾯可以放置多个控件实现程序功能 |
QDialog | 基于对话框的程序,对话框⼀般⽤于弹窗,也可以⽤于主界⾯显⽰。对话框是从QWidget继 承⽽来的,并丰富了⼀些功能,如模态显⽰和返回值等 |
基类之间的关系
6.认识对象模型(对象树)
1.是什么?
在Qt中创建很多对象的时候会提供⼀个Parent
对象指针QObject
是以对象树的形式组织起来的 当创建⼀个QObject
对象时,会看到QObject
的构造函数接收⼀个QObject
指针作为参数,这个参数就是parent
,也就是⽗对象指针 这相当于,在创建QObject
对象时,可以提供⼀个其⽗对象,创建的这个QObject
对象会⾃动添加到其⽗对象的children()
列表当⽗对象析构的时候,这个列表中的所有对象也会被析构(这⾥的⽗对象并不是继承意义上的⽗类) 使用对象树,把内容组织起来,最主要的目的是为了能够在合适的时机(窗口关闭/销毁),把这些对象统一进行释放Qt对象图2.解决内存问题
1.如何解决?
Qt引⼊对象树的概念,在⼀定程度上解决了内存问题 当⼀个QObject
对象在堆上创建的时候,Qt会同时为其创建⼀个对象树 不过,对象树中对象的顺序是没有定义的,这意味着,销毁这些对象的顺序也是未定义的 任何对象树中的QObject
对象delete
的时候 如果这个对象有parent
,则⾃动将其从parent
的children()
列表中删除如果有孩⼦,则⾃动delete
每⼀个孩⼦ Qt保证没有QObject
会被delete
两次,这是由析构顺序决定的 2.如何做?
创建对象的时候,在构造函数中,指定父对象,此时该对象才会被挂到对象树上 如果该对象没有被挂到对象树上,就必须要记得手动释放 尽量避免在栈上创建Qt对象,可能存在提前释放的问题 如果QObject
在栈上创建,Qt保持同样的⾏为,正常情况下,这也不会发⽣什么问题如下代码,没问题 作为⽗组件的window
和作为⼦组件的quit
都是QObject
的⼦类quit
的析构函数不会被调⽤两次,因为标准C++要求,局部对象的析构顺序应该按照其创建顺序的相反过程因此,这段代码在超出作⽤域时,会先调⽤quit
的析构函数,将其从⽗对象window
的⼦对象列表中删除,然后才会再调⽤ window的析构函数 QWidget window;QPushButton quit("Quit", &window);
如下代码,有问题 情况有所不同,析构顺序出现了问题,作为⽗对象的window
会⾸先被析构,因为它是最后⼀个创建的对象在析构过程中,它会调⽤⼦对象列表中每⼀个对象的析构函数 也就是说,quit
此时就被析构了 然后,代码继续执⾏,在window
析构之后,quit
也会被析构 因为quit
也是⼀个局部变量,在超出作⽤域的时候当然也需要析构但是,此时已经是第⼆次调⽤quit
的析构函数了 C++不允许调⽤两次析构函数,因此,程序崩溃了 QPushButton quit("Quit");QWidget window;quit.setParent(&window);
在Qt中,尽量在构造的时候就指定parent对象,并且⼤胆在堆上创建 通过new
的方式创建对象,是为了把这个对象的生命周期交给Qt的对象树来统一管理 3.举例说明
QWidget
是能够在屏幕上显⽰的⼀切组件的⽗类 QWidget
继承⾃QObject
,因此也继承了这种对象树关系,⼀个孩⼦⾃动地成为⽗组件的⼀个⼦组件因此,它会显⽰在⽗组件的坐标系统中,被⽗组件的边界剪裁 例如:当⽤⼾关闭⼀个对话框的时候,应⽤程序将其删除,属于这个对话框的按钮、图标等应该⼀起被删除,因为这些都是对话框的⼦组件 当然,也可以⾃⼰删除⼦对象,它们会⾃动从其⽗对象列表中删除 例如:当删除了 ⼀个⼯具栏时,其所在的主窗⼝会⾃动将该⼯具栏从其⼦对象列表中删除,并且⾃动调整屏幕显⽰ 4.总结
Qt的对象树机制虽然在⼀定程度上解决了内存问题,但是也引⼊了⼀些值得注意的事情这些细节在开发过程中很可能时不时跳出来烦扰⼀下,所以,最好从开始就养成良好习惯7.Qt父子对象
一般通过代码来构造界面的时候,通常会把构造界面的代码放到Widget/MainWindow
的构造函数中一般会给当前这个对象设置一个父对象,即将该对象加入到父对象的对象树中Qt中使⽤⽗⼦关系决定该控件"在哪⾥" 8.Qt中乱码的处理
Qt提供了一个qDebug()
工具,可以帮助用户自动处理编码方式 正常当作std::cout
一样使用即可用法:qDebug() << "SnowK";
另一个好处:打印的调试日志,是可以通过编译开关统一进行关闭的 9.注意 && 提要
Qt中规定,任何对于GUI上内容的操作,必须在主线程中完成 当尝试在⾃⼰的线程中对界⾯元素进⾏修改时,Qt程序往往会直接崩溃这样的约定主要是因为GUI中的状态往往是牵⼀发动全⾝的,修改⼀个地⽅,就需要同步的对其他内容进⾏调整 例如:调整了某个元素的尺⼨,就可能影响到内部的⽂字位置,或者其他元素的位置,这⾥⼀连串的修改,都是需要按照⼀定的顺序来完成的 由于多线程执⾏的顺序⽆法保障,因此Qt从根本上禁⽌了其他线程修改GUI状态,避免后续的⼀系列问题QByteArray
⽤于表⽰⼀个字节数组,可以很⽅便的和QString
进⾏相互转换 使⽤QString
的构造函数即可把QByteArray
转成QString
使⽤QString
的toUtf8()
即可把QString
转成QByteArray