QT --- 初识QT

ops/2024/9/20 1:29:32/ 标签: qt, 开发语言

一、通过代码构建helloworld界面

一般通过代码来构造界面的时候,通常会把构造界面的代码放到Widget/MainWindow的构造函数中。

Qt中每个类都有对应同名的头文件

上古时期,Qt用的是这种风格的文件。1998年之后,C++标准成立了,C++98标准。规定,包含头文件,统一使用#include<cstdio>代替原有的#include<stdio.h>

Lable叫做标签,界面上一个用来显示内容字符串的控件,创建对象的时候,可以直接堆上创建,也可以在栈上创建。跟推荐在堆上创建对象。


this,给当前这个label对象,指定一个"父对象" this 就是Widget w。给这个对象里面设置一个文本,设置控件中,要显示的文本是啥。

Qt诞生于1991年,C++还没有形成标准,C++更没有标准库这样的改变了。当时,如何表示一个字符串,可以使用C风格字符串,也可以使用C++的string。Qt为了让自己的开发能变得的顺畅,就自己发明了一套轮子,搞了一系列的基础类,来支持Qt的开发,

很多年之后,上述这些容器等内容,已经打磨的很好了,形成了C++标准。

很显然,这些已经引入的Qt自己包装好的这些容器类,也不可能删了。就只能和现有的标准库中的容器类共存了。后续的代码中,还会经常见到QString这样的一些东西,而很少见到std::string Qstring和std::string之间也能很方便的相互转换。

在QString中也提供了C风格字符串作为参数的构造函数,不显示构造QString,上述代码中,C风格字符串也会隐式构造程QString对象。QString对应的头文件,已经被很多Qt内置的其他类都包含了。所以我们不需要显式包含QString头文件。通过代码创建QLable默认式在左上角。如果想放到其他的位置,也是可以的。

代码:

二、内存泄露问题的讨论。

这个代码,new了对象之后,咋没有delete呢?不delete不就出现内存泄露了吗?

关注内存泄漏,是要融入到DNA中的事情,内存泄露是一个非常可怕的事情。

三、对象树

上面的代码在QT中不会产生内存泄漏,lable对象会适合的时候被析构释放 ~~ 虽然没有手动写delete,确实能释放。之所以能够把对象释放掉,主要是因为把这个对象挂到了对象树上。前端开发也涉及到了类似的对象树(DOM),本质上也是一个树形结构(N叉树),通过树形结构把界面上的各种元素组织起来。Qt中也有一个对象书树也是N叉树,把界面上的各种元素组织起来了。

通过这个树形结构,就把界面上要显示的这些控件对象都组织起来了。使用对象树,把这些内容组织起来,最主要的目的,就是为了能够在合适的时机,把这些对象统一进行释放。

如果树上的这些对象,统一销毁时最好不过的,如果某个对象提前销毁,此时就会导致对应的控件就在界面上不存在了。此处通过new的方式创建对象,也就是为了把这个对象生命周期,交给Qt的对象树来统一管理。

当把对象改成在栈上创建,此时就可以看到,运行起来的程序无法显示出hello world此时lable对象随着构造函数的结束就销毁了。

我们来验证一下对象树的存在性。可以用自己编写的类来实现验证。创建自定义类,最主要的目的,是自定义一个析构函数,在析构函数中,完成打印,方便我们看到最终的自动销毁对象的结果!!

#include <QLabel>
class MyLable : public QLabel
{
public:MyLable(QWidget* parent);~MyLable();
};#endif // MYLABLE_H
#include "mylable.h"
#include <iostream>
MyLable::MyLable(QWidget* parent):QLabel(parent)
{}MyLable::~MyLable()
{std::cout << "对象被销毁" << std::endl;
}

日志有:说明析构函数是执行了,虽然没有手动delete,但是由于把MyLable挂到了对象树上。此时窗口被销毁的时候,就会自动销毁对象树中的所有对象。MyLable的析构时执行到了的。

预期打印的时被销毁三个中文,但是实际的显示效果,出现了乱码。原因就是编码方式不匹配。

关于乱码问题的解释:

在计算机中,一个汉字,占多少个字节?

针对这个问题,只要你回答出具体的数字,就一定时错的!。前提条件:当前中文编码使用的是哪种方式(字符集)。计算机种存储的都是二进制码。英文字母是通过ASCII码表,规定了每个字符,都有一个对应的数字来表示。只是表示英文,一个字节足够了,毕竟英文字母数目非常有限。

中文一共多少个汉字呢?日常的常用字,大概是4000多个。算上各种生僻字,总数差不多6W多个。我们仍然使用一个大表格,给每个汉字,分配一个整数即可。那么具体这个表格是什么样子。具体每个数字都使用哪个数字表示这个事情就不一定了,字符集表示汉字的字符集,其实是有很多种的不同的字符集,表示同一个汉字,使用的数字并不相同!

目前表示汉字字符集,主要两种方式

1、GBK中国大陆 使用2个字节表示一个汉字。

2、UTF-8变长编码,表示一个符号,使用的字节数有变化。2 - 4字节,但是在utf-8中,一个汉字,一般是3个字节。Linux中默认就是utf-8。

如果你字符串本身是utf-8编码的,但是终端是按照GBK的方式解析的显示的,此时就会出现乱码,(拿着utf-8这里的数值,去查询gbk的码表)此时就会出现乱码了。

Qt Creator内置的终端是utf-8的方式来显示字符串吗?

这个终端好像不能设置字符编码,既然出现乱码了,这里不是utf-8了。当前表示中文,主流的方式,还得是utf-8,它支持各种语言文字。Qt中有一个东西,QString,是可以帮助我们自动的处理编码方式的,不只是QString,Qt也提供了专门用来打印日志的工具,也能自动处理编码方式。Qt中提供了QDebug工具,借助这个工具,就可以完成打印日志的过程,很好的处理字符编码了。

 QDebug是Qt中的类,又不会直接使用这个类。

这个宏,封装了QDebug对象,直接使用qDebug()这个东西就可以当作cout来使用。后续在Qt中,如果想通过打印日志的方式,输出一些调试信息,都有限使用qDebug,使用qDebug还有一个好处,打印的调试日志,是可以统一进行关闭的。如果你的程序发布给用户,不希望用户看到这些日志的!qDebug可以通过编译开关,来实现一键式关闭。

小结:

1、认识了QLabel类,能够在界面上显示字符串。

       通过setText来设置的,参数QString。这是一个历史原因

2、内存泄漏/文件资源泄漏。

3、对象树,Qt中通过对象树,来统一的释放界面的控件对象。Qt还是推荐使用new的方式在堆上创建对象,通过对象树,统一释放资源。创建对象的时候,在构造函数中,指定父对象此时才会挂到对象树上。如果你的对象没有挂到对象树上,就必须记得手动释放。

4、通过继承自Qt内置的类,就可以达到对现有控件进行功能扩展的效果。Qt内置的QLabel,没法看到销毁过程,为了看清楚我们就创建类MyLable,继承QLabel重写析构函数。在析构函数,加上日志,直观的观察到对象释放的过程了。也可以重写控件中的任何功能,不仅仅是构造,达到功能扩展的目的,面向对象继承本质上就对现有的代码进行扩展。我们要学习,也要思考需要悟道。

5、乱码问题和字符集的问题。在MySQL中很多地方都涉及到。

6、如何在Qt中打印日志,作为调试信息。使用Qt中推荐的qDebug()完成日志的打印。

四、使用输入框实现helloworld

完成一个helloworld可以通过很多种控件来实现。

使用编辑框来完成hello world

单行编辑框 QLineEdit

多行编辑框 QTextEdit

代码:

使用纯代码的方式实现:

#include "widget.h"
#include "ui_widget.h"
#include <QLineEdit>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QLineEdit* qline = new QLineEdit(this);qline->setText("hello world");
}Widget::~Widget()
{delete ui;
}

五、使用按钮实现helloworld

使用pushbutton就是一个普通的按钮。按钮可以设置一个点击效果。Qt中的信号槽机制。本质就是给按钮的点击操作关联上一个处理函数,当用户点击的时候,就会执行这个处理函数。、

需要使用connect(),Linux网络编程也学过这个函数,这个函数用来建立连接,然后才能读写数据。Qt中的connect是QObject这个类提供的静态函数,这个函数的作用就是连接信号和槽。和TCP的建立连接操作没有任何的关系。第一个参数谁发的信号,ui->pushbutton,访问到form file(ui文件)中创建的控件!此时就会给这个控件分配一个objectName属性。这个属性的值,要求是在界面上唯一的。不能和别人重复。会自动生成一个,也可以手动修改换成别的。

第二个参数传入,关联到父类中,然后

点击按钮的时候就会自动触发这个信号。

this 谁来处理这个信号,第四个参数具体怎么处理。

代码:

#include "ui_widget.h"
#include <QObject>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(ui->pushButton,&QPushButton::clicked,this,&Widget::Handler);
}Widget::~Widget()
{delete ui;
}void Widget::Handler()
{if(ui->pushButton->text() == "hello world")ui->pushButton->setText("hello qt");elseui->pushButton->setText("hello world");
}

使用纯代码的方式实现。

#include "widget.h"
#include "ui_widget.h"
#include<QObject>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//使用纯代码的方式实现helloworld,信号槽机制//button我们定义为了Widget类中的私有成员。button = new QPushButton(this);button->setText("helloworld");connect(button,&QPushButton::clicked,this,&Widget::Handler);}Widget::~Widget()
{delete ui;
}void Widget::Handler()
{if(button->text() == "helloworld"){button->setText("hello qt");}else{button->setText("helloworld");}
}

 左边为纯代码创建,右边为ui创建

对于纯代码版本,按钮对象是咱们自己new的。为了保证其他函数中能够访问这个变量,就需要把按钮对象设定为Widget类的成员变量。右边的按钮对象不需要咱们自己new,new对象的操作已经被Qt自动生成了。而且这个按钮对象,已经作为ui对象里的一个成员变量了。也无需作为Widget的成员。实际开发中,这两种都很主要,难分主次!如果当前程序界面,界面内容是比较固定的,此时就会以图形化的方式来构造界面。但是如果你的程序界面,经常要动态变化,此时就会以代码的方式来构造界面。这两种方式,哪种方便就用哪种。而且两种方式也可以配合使用,后面这两种方式都会涉及到。

六、Qt中的命名规范

给变量/函数/文件/类 起名字,是非常有讲究的。

1、起的名字要有描述性,不要使用abc,xyz这种比较无规律的名字来描述。

2、如果名字比较长,有多个单词构成,就需要使用适当的方式来进行区分不同的单词。Qt中偏好使用大写字母来进行单词分割的。这种命名法叫做驼峰命名法。一种是小驼峰给变量命名,一种是大驼峰给类命名。我们入乡随俗。你公司中使用的项目,使用的驼峰/蛇形/其他。

七、认识Qt窗口坐标体系

坐标体系:以左上角为原点(0,0),右边为x,向下为y。平面直角坐标系(笛卡尔坐标系)

给Qt的某个控件,设置位置,就需要指定坐标,对于这个控件来说坐标系原点就是相对于父窗口的

 代码:

#include "widget.h"
#include "ui_widget.h"
#include<QObject>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//使用纯代码的方式实现helloworld,信号槽机制//button我们定义为了Widget类中的私有成员。button = new QPushButton(this);button->setText("helloworld");connect(button,&QPushButton::clicked,this,&Widget::Handler);button->move(200,300);}

可以使用move这个函数来移动控件的位置。坐标背后的单位:像素。 


http://www.ppmy.cn/ops/111985.html

相关文章

《深度学习》深度学习 框架、流程解析、动态展示及推导

目录 一、深度学习 1、什么是深度学习 2、特点 3、神经网络构造 1&#xff09;单层神经元 • 推导 • 示例 2&#xff09;多层神经网络 3&#xff09;小结 4、感知器 神经网络的本质 5、多层感知器 6、动态图像示例 1&#xff09;一个神经元 相当于下列状态&…

软件工程知识点总结(7):软件项目管理

目录 1 软件项目管理 2 进度计划 2.1 WBS 2.2 WBS 工作分解结构 2.3 制定进度计划 ——Gantt 1 软件项目管理 软件项目管理是指软件生命周期中软件管理者所进行的一系列活动&#xff0c;其目的是在 一定的时间和预设范围内有效的利用人力、资源、技术和工具&#xff0c;使…

[数据集][目标检测]智慧交通铁路异物入侵检测数据集VOC+YOLO格式802张7类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;802 标注数量(xml文件个数)&#xff1a;802 标注数量(txt文件个数)&#xff1a;802 标注类别…

F12抓包11:UI自动化 - Recoder(记录器)

课程大纲 使用场景&#xff08;导入和导出&#xff09;: ① 测试的重复性工作&#xff0c;本浏览器录制并进行replay&#xff1b; ② 导入/导出录制脚本&#xff0c;移植后replay&#xff1b; ③ 导出给开发进行replay复现bug&#xff1b; ④ 进行前端性能分析。 1、录制脚…

Eureka原理与实践:构建高效的微服务架构

Eureka原理与实践&#xff1a;构建高效的微服务架构 引言 随着微服务架构的日益普及&#xff0c;服务的数量和复杂性不断增加&#xff0c;如何有效地管理这些服务成为了一个重要的挑战。Eureka&#xff0c;作为Netflix开源的服务发现组件&#xff0c;凭借其简单、健壮的特性&…

SpringBoot 消息队列RabbitMQ使用延迟消息插件 接收延迟消息

介绍 需要确保MQ已经安装好了延迟插件。 创建延迟交换机与队列 RabbitListener(bindings QueueBinding(value Queue(value "test.queue",durable "true"),exchange Exchange(value "test.fanout",delayed "true"),key {&quo…

23ai DGPDB,Oracle资源池战略的最后一块拼图

Oracle对资源池是有执念的&#xff01; 在我看来&#xff0c;这种执念一方面是应用架构的微服务化&#xff0c;数据库被拆分的越来越小&#xff0c;而服务器的硬件能力是不断提升的&#xff0c;CPU核心数、内存和存储的容量都按照摩尔定律在不断增加&#xff0c;这就使得数据库…

QUIC的loss detection学习

PTO backoff backoff 补偿 /ˈbkɒf/PTO backoff 是QUIC&#xff08;Quick UDP Internet Connections&#xff09;协议中的一种机制&#xff0c;用于处理探测超时&#xff08;Probe Timeout, PTO&#xff09;重传策略 它逐步增加探测超时的等待时间&#xff0c;以避免网络拥塞…

P1056 [NOIP2008 普及组] 排座椅(模拟)

1.用x,y数组存放切了几对学生&#xff0c;用数组的下标记录切的位置 2.按照题目要求k和l依次取出最大的数组的值&#xff0c;并将其变为-1&#xff0c; 再次循环取出第二大的值&#xff0c;之后所有下标为-1的的下标就是切的学生对多的 3.切的意思是把两个学生分开 #includ…

初学Linux(学习笔记)

初学Linux&#xff08;学习笔记&#xff09; 前言 本文跳过了Linux前期的环境准备&#xff0c;直接从知识点和指令开始。 知识点&#xff1a; 1.目录文件夹&#xff08;Windows&#xff09; 2.文件内容属性 3.在Windows当中区分文件类型是通过后缀&#xff0c;而Linux是通过…

如何理解BCEWithLogitsLoss()

1.示例1 logit[0.5 -1.0 2.0] targets[1 0 1]# δsigmoid(x) pδ(logits)[δ(0.5) δ(-1.0) δ(2.0)][0.6225 0.2689 0.8808]loss1 -[1 log(0.6225) 0 log(1 - 0.6225)] ≈ 0.4744 loss2 -[0 log(0.2689) 1 log(1 - 0.2689)] ≈ 0.3133 loss3 -[1 log(0.8808) 0 …

Linux tr命令

参考资料 【 tr 】コマンド――テキストファイルの文字を置換する&#xff0f;削除する【Linux】trコマンド使ってみた【trコマンド】 目录 一. 基本语法二. 替换2.1 匹配模式进行替换2.2 只支持字符的替换 三. 选项3.1 -d 删除指定字符3.2 -s 替换多个重复出现的字符为单个字…

new/delete和malloc/free到底有什么区别

new和malloc 文章目录 new和malloc前言一、属性上的区别二、使用上的区别三、内存位置的区别四、返回类型的区别五、分配失败的区别六、扩张内存的区别七、系统调度过程的区别总结 前言 new和malloc的知识点&#xff0c;作为一个嵌入式工程师是必须要了解清楚的。new和malloc的…

【从问题中去学习k8s】k8s中的常见面试题(夯实理论基础)(二十九)

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

python画图|极坐标下的3D surface

前述学习过程中&#xff0c;我们已经掌握了3D surface的基本绘制技巧&#xff0c;详见链接&#xff1a; python画图|3D surface基础教程-CSDN博客 基础教程中的3D surface绘制位于笛卡尔坐标系&#xff0c;但有时候会用到极坐标绘图。虽然我们已经学过简单的极坐标绘图技巧&a…

基于paddleocr的批量图片缩放识别

说明 在进行ocr文字识别的时候&#xff0c;有时候我们需要使用批量测试的功能&#xff0c;但是有些图片会识别失败或者个别根本识别不出来&#xff0c;这时候我们可以通过对原图片进行缩放&#xff0c;提高图像的分辨率&#xff0c;然后再次识别&#xff0c;这样可以大大提高图…

【Java EE】冯·诺依曼体系结构及其在 JavaEE 中的应用

1. 引言 冯诺依曼体系结构&#xff08;Von Neumann Architecture&#xff09;是现代计算机体系结构的基础&#xff0c;由数学家约翰冯诺依曼于 1945 年提出。这种架构定义了计算机的基本结构&#xff0c;包括处理器、内存、输入/输出设备和存储设备。冯诺依曼架构影响了计算机…

物品识别——基于python语言

目录 1.物品识别 2.模型介绍 3.文件框架 4.代码示例 4.1 camera.py 4.2 interaction.py 4.3 object_detection.py 4.4 main.py 4.5 运行结果 5.总结 1.物品识别 该项目使用Python&#xff0c;OpenCV进行图像捕捉&#xff0c;进行物品识别。我们将使用YOLO&#xff08…

element-plus组件问题汇总

element-plus组件问题汇总 一、el-select 1. 下拉选项实现添加全部 问题描述&#xff1a;value为空时&#xff0c;select框中不显示全部选项&#xff0c;但是下拉列表中全部显示是勾选状态 图片&#xff1a; 解决办法&#xff1a;添加 :empty-values“[null, undefined]” …

后端开发刷题 | 数字字符串转化成IP地址

描述 现在有一个只包含数字的字符串&#xff0c;将该字符串转化成IP地址的形式&#xff0c;返回所有可能的情况。 例如&#xff1a; 给出的字符串为"25525522135", 返回["255.255.22.135", "255.255.221.35"]. (顺序没有关系) 数据范围&…