QT系列(四)对象树


前言

  • 前端网页开发也涉及到类似的对象树,本质上是一个树形结构(N叉树),通过树形结构把界面上的各种元素组织起来。
  • QT中也是类似搞了一个对象树,把界面上各种元素组织起来。比如QWidget下面会有QLabel ,QpushButton, QListWidget,其中QListWidget还有很多节点,通过树形结构将界面上显示的控件对象组织起来,方便统一对对象进行释放。窗口销毁时,统一释放对象,提前销毁就会不在窗口上存在该标签。

一、挂在树上

之前通过new的方式创建,就是为了将它交给QT对象树统一管理。如果栈上创建就会出现提前释放。
如果我们将上文代码改成在栈上,hello world无法显示。

二、不delete的原因

1.自己创建类展示释放效果

在这里插入图片描述
在这里插入图片描述

然后就可以看到QTCreater生成的代码,但是没完全生成。mulabel.h中可以看到warning提示,原因是没有包含相关的头文件,手动包含即可。

#include<QLabel>//手动添加
class Mylabel : public QLabel
{
public:
    //Mylabel();
    MyLabel(QWidget* parent);
};

#endif // MYLABEL_H

构造函数使用带QWIdget* 版本的,确保自己的对象能够加到对象树上。

2.cpp文件

在QTCreater中,可以通过F4切换对应的头文件和.cpp文件
vim中采用":A"的方式完成切换,:AT新开一个标签页显示类

#include "mylabel.h"

Mylabel::Mylabel(QWidget* parent):QLabel(parent)
{

}

目的是调用父类QLabel构造函数,让自己类的对象加入QT对象树中。

3.析构函数

创建自定义类最主要的目的是自定义一个析构函数,在析构函数中完成打印,看到自动销毁对象的效果。

光标放在写好的析构函数上,按alt+回车,可以看到在mylabel.cpp中添加定义,再次按回车完成

Mylabel::~Mylabel()
{
    std:: cout << "Mylabel被销毁"<<std::endl;
}

4.widget中创建对象

#include "widget.h"
#include "ui_widget.h"
#include "mulabel.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    Mulabel* label = new Mylabel(this);
    label->setText("hello world");
    //widget中添加label对象
}

Widget::~Widget()
{
    delete ui;
}

使用自己定义的Mylabel代替原来的QLabel,所谓的继承本质上是扩展,保持原有功能不变的基础上给对象扩展出一个析构函数,通过析构函数打印相关的内容,方便看到delete的效果。

运行效果

虽然没有delete但是执行力
虽然没有delete但是执行了析构函数,说明不用delete也会自动析构。
但是汉字的显示出现了乱码:

乱码问题有且只有一个,编码方式不匹配
计算机中一个汉字几个字节取决于中文编码的方式,比如英文字符是根据ascll码表来对应的,汉字也是使用一个大表格,给每个汉字分配整数

目前的汉字字符集主要是两种方式

  1. GBK,两个字节表示一个汉字(windows默认)
  2. UTF-8 变长编码,字节数有变化2-4,一般是三个字节(linux默认)

具体的编码数值可以通过在线工具查看

  • 对于mylabel.cpp,右键在explorer中查看,在mylabel.cpp中右键用记事本打开,文件另存为,最下面就会有当前文件编码方式,如果显示utf-8,说明这个文件是utf-8编码
    该终端不能设置字符编码,出现乱码因此不是utf-8
  • QT中有QString,可以帮助自动处理编码方式,也有专门打印日志的 工具,也能自动处理编码方式

QDebug显示工具专门进行打印

qDebug工具,可以完成打印日志的过程,很好的处理字符编码(不需要程序员进行关注了)

#include<QDebug>//QT类但又不直接使用
Mylabel::~Mylabel()
{
    //std:: cout << "Mylabel被销毁"<<std::endl;
    qDebug()<< "Mylabel被销毁";//注意头文件
    //宏中封装了QDebug,直接使用相当于cout
}

在这里插入图片描述

优先使用qdebug来通过打印日志的方式输出一些调试信息。cout对于编码的处理不太好,windows上容易出现乱码(linux一般没事,默认编码为utf-8)

qDebug可以统一关闭,输出的日志是开发阶段调试的时候使用,如果程序发布给用户,不希望用户看到,可以通过编译开关统一关闭。

总结

  1. 认识QLabel类,可以显示字符串,通过setText进行设置。参数QString(QT中将C++很多类进行重新封装,历史原因),
  2. 内存泄漏
  3. 对象树,QT中通过对象树,统一的释放界面的控件对象。QT还是推荐new的方式在堆上创建对象,通过对象树统一释放对象。而创建对象时,在构造函数中,指定父对象(此时才会挂到对象树上)
    如果没有挂到对象树上,就必须手动释放
  4. 通过继承自QT内置的类,就可以达到对现有控件进行功能扩展效果。QT内置的QLabel,没法看到销毁过程,因此常见Mylabel继承自QLabel.然后在析构函数中加上日志,直观的观察到对象的释放过程。

可以重写控件的任何功能,不仅是析构函数达到功能扩展的目的。

  1. 乱码问题和字符集 Mysql
  2. QT中打印一个日志作为调试信息,cout可以但不是上策,(字符编码处理的不好,也不方便统一关闭)QT中推荐使用qDebug完成日志的打印

日志可以解决调试器无法解决的小概率问题,不论是哪种方式,都是观察程序执行的中间过程和中间结果

  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值