Qt_QWidget的基本使用

目录

1、以界面方式创建label控件

1.1 观察ui文件xml代码 

1.2  观察ui_widget.h里的C++代码

2、以代码方式创建label控件 

2.1 对象树

2.2 验证对象树的销毁操作 

3、Qt下的编码规则 

结语 


前言:

        使用Qt Creator新建一个QWidget项目,QWidget本身就是一个控件,只不过该控件上可以存放其他的控件,QWidget是生成图形化界面的一个基础条件。生成一个带有控件的界面有两种方式:1、图像化的方式,2、代码的方式。然后对控件进行分析,观察当控件被创建出来时,其他文件的内容是否发生改变。

        控件指的是带有不同功能的模块,界面上的一切都可以称为是控件,Qt Designer(ui文件)左边一栏就是Qt内置的控件:

1、以界面方式创建label控件

        待新建了QWidget后(如何新建QWidget项目请看:Qt_了解Qt Creator),创建控件的方法很简单,打开ui文件,然后在左栏下滑找到label控件,将其拖到界面上,至此就完成了控件的创建了,并且可以更改label的文本信息:

         点击运行可以看到界面中出现了hello world的字样,这就是label的文本显示信息:

1.1 观察ui文件xml代码 

        对比创建控件之前和之后的ui文件xml代码,如下图:

        运行之所以可以在界面中显示控件,是因为qmake会基于该xml代码生成一段C++代码,然后通过该C++代码生成最终的界面。

1.2  观察ui_widget.h里的C++代码

       在界面上依靠xml代码显示出了对应的控件,那么在代码逻辑中也必须支持这一控件的存在,通过观察ui_widget.h来得出这一结论:

2、以代码方式创建label控件 

        除了上述的界面方式,还可以通过纯代码的方式实现和上述一样的界面,因为在Qt中,所有的控件都被封装成一个类,因此创建一个控件可以抽象的看成创建一个类。不过创建控件的代码不是写在main函数中的,而是写在widget.cpp中,代码实现方法如下:

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

#include <QLabel>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QLabel* label = new QLabel(this);
    label->setText("hello world");
}

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

        测试结果:

        虽然正常将控件打印到屏幕上,但是和上述的结果还是有区别的,这里的label处于窗口的左上角。 

2.1 对象树

        在上述代码中,将this指针作为形参传给new出来的对象,这么做的目的就是把该控件挂到对象树上,对象树是一种树型结构,可以理解为最初树上只有Widget这一个节点,后续创建的新控件可以指定挂到Widget节点下,只要传this指针即可。

        那么对象树的作用是什么呢?我们发现上述代码中,使用了new进行申请空间,但是整个代码没有对new出来的空间进行delete,原因就是对象树会在窗口关闭时对树上的所有控件进行释放。即对象树将这些控件都组织起来,以便在合适的时机由系统自动释放这些控件,不仅降低了程序员的工作量,还降低了引发内存泄漏的可能性。对象树概念图如下:

        那针对上述new的逻辑,如果直接创建一个局部对象,是否可以做到既不用手动释放又可以实现一样的界面呢?测试如下:

        发现界面中没有打印出label控件,原因就是局部对象出了作用域就被销毁了,即当main函数中指向到show函数时,这个控件已经不存在了,导致打印出来的界面什么也没有。因此,综上所述使用代码创建控件时,大部分场景下必须使用new的形式来创建。 

2.2 验证对象树的销毁操作 

        可以通过创建一个继承QLabel的子类(myLabel),然后在该类的析构函数出进行打印信息(方便观察析构是否被调用),若对象树有自动释放控件的能力,那么该类的析构函数一定会被调用,myLabel的代码如下:

        mylabel.h文件代码:

#ifndef MYLABEL_H
#define MYLABEL_H

#include <QWidget>
#include <QLabel>
#include <iostream>

class myLabel : public QLabel
{
    Q_OBJECT
public:
    myLabel(QWidget* parent);
    ~myLabel();
};

#endif // MYLABEL_H

        mylabel.cpp文件代码:

#include "mylabel.h"

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

}

myLabel::~myLabel()
{
    std::cout<<"myLabel的析构函数被调用"<<std::endl;
}


        然后在widget的构造函数内,使用myLabel标签,因为myLabel继承了QLabel,所以他也具有标签的功能,并且还可以附加一些自带的功能:

#include "widget.h"
#include "ui_widget.h"
#include "mylabel.h"

#include <QLabel>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //QLabel* label = new QLabel(this);
    //QLabel label;
    //label->setText("hello world");
    //label.setText("hello world");

    //使用自己的mylabel作为标签
    myLabel* mylabel = new myLabel(this);
    mylabel->setText("hello mylabel");
}

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

        测试结果:

        从结果可以看到,在关闭界面时,确实触发了myLabel的析构函数,说明对象树确实可以自动释放树上的控件,只不过打印出来的数据是乱码。

3、Qt下的编码规则 

        上述乱码的原因是:文件的编码方式和终端的编码方式不一样。比如字符串本身是utf8编码保存的,但是终端(控制台)是按照gbk的方式来解析字符串的,这就会出现乱码。因为解析字符串的规则和字符串存储的规则不一致

        解决方式:使用Qt中专门提供了一个打印的工具qDebug(),他是一个宏。直接使用该工具就可以正常打印了,测试结果如下:

结语 

        以上就是关于QWidget基本使用的讲解,创建控件的两种方式各有各的优势,具体用哪一种进行开发则根据当时的场景来判断,其次,理解界面对于控件的管理机制也能够提升对Qt界面开发的认知,当然最重要的是理解QWidget的含义。

        最后如果本文有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!!  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

安权_code

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

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

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

打赏作者

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

抵扣说明:

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

余额充值