[Qt][初识Qt]详细讲解


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
    • 注意QStringstd::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,则⾃动将其从parentchildren()列表中删除
      • 如果有孩⼦,则⾃动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
    • 使⽤QStringtoUtf8()即可把QString转成QByteArray
  • 21
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DieSnowK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值