当前位置: 首页 > news >正文

第二章:Qt第一个程序

目录

1、Qt Hello World程序

1.1、使用标签实现

1.1.1、使用图形化方式

1.1.2、使用纯代码方式

1.2、内存泄漏问题

2、对象树

2.1、创建新文件

2.2、乱码问题

3、多种方式实现

3.1、使用编辑框实现

3.1.1、使用图形化的方式

3.1.2、使用纯代码的方式

3.2、使用按钮实现

3.2.1、使用图形化方式

3.2.2、使用纯代码的方式

3.3、图形化和纯代码对比

4、Qt中的注意事项

4.1、命名规范

4.2、快捷键

4.3、使用帮助文档

5、Qt窗口坐标系


1、Qt Hello World程序

1.1、使用标签实现

有两种方式可以实现,一种是通过写代码的方式实现,另一种是通过图形化的方式。

1.1.1、使用图形化方式

1、双击:"widget.ui"文件;

2、拖拽"标签"至UI设计界面中,并双击修改标签内容;

例如:

同时Qt Designer的右上角,通过树形结构,显示了当前界面上都有哪些控件。如下:

运行结果为:

刚才往界面上拖拽了一个QLabel控件,此时.ui文件中就会多出如下这一段代码:

进一步的qmake就会在编译项目的时候,基于这个内容生成一段C++代码,然后通过这个C++代码来构建出界面内容了。例如:在ui_widget.h头文件中就会有如下中的几段代码。

1.1.2、使用纯代码方式

一般我们通过代码来构造界面的时候,通常会把构造界面的代码放到Widget的构造函数中。例如:

注意:Qt中每个类都有一个对应的同名的头文件。下面的这个以.h为后缀的这个文件是过去Qt使用的风格,后来使用了不带.h为后缀的这种风格的头文件。Lable就是标签的意思,就是一个可以在界面上显示字符串的控件。

Qt为了让自己的开发变的能更加流畅,就发明了一套自己的轮子,搞出了一系列的基础类,来支持Qt的开发,包括但不限于QString、QVector、QList、QMap等等。如下图所示的QString。因此,写Qt代码时,既可以使用C++标准库中的容器,也可以使用Qt中搞的这一套容器,但是Qt的原生API中,涉及到的接口,用的都是Qt自己的这一套容器。

运行结果为:

1.2、内存泄漏问题

在我们上面的代码中,在堆上new了一个对象,但是并没有把该对象delete掉,如下图所示:

那这样是不是就内存泄漏了呢?先给出结论,上面的代码并不会导致内存泄漏,lable对象会在合适的时候被析构释放。之所以能够把对象释放掉,主要是因为把这个对象给挂到了对象树上。

注:内存泄漏是一个非常严重的问题,不仅仅是内存泄漏,包括文件描述符泄漏等同类问题,都是非常严重的。

2、对象树

前端开发(指网页开发)中也涉及到类似的对象树(DOM),本质上是一个N叉树,通过树形结构把界面上的各种元素组织起来。在Qt中也是类似,也是有一个对象树,也是一个N叉树,把界面上的各种元素组织起来。通过树形结构,就把界面上要显示的这些控件对象都组织起来了。

使用对象树,把这些内容组织起来,最主要的目的,就是为了能够在合适的时机(窗口销毁或关闭时),把这些对象统一进行释放。如果某个对象提前销毁,此时就会导致对应的控件就在界面上不存在了。

试想一下,如果在栈上创建对象,就可能会出现“提前释放”的问题,例如:在栈上创建对象

运行结果为:

从运行结果就可以看到,hello world无法正常显示。原因就是此处的label对象随着构造函数的结束就销毁了,因此hello world就无法显示了。

2.1、创建新文件

接下来我们搞一个类,用来演示自动销毁对象的效果。

首先点击“文件”中的“新建文件或项目”。

然后选择“C++ Class”。

选择"choose",弹出如下界面:

点击"下⼀步",弹出如下对话框:

点击"完成"之后,手动创建类的头文件以及源文件会自动添加到目标工程中,如下图所示:

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

例如:

mylabel.h文件:

mylabel.cpp文件:

widget.cpp文件:

程序运行结果为:

当点击程序运行结果上面的×号时,程序会打印一句话,如下图所示:

从运行结果我们可以看到,虽然我们没有手动delete,但是由于把MyLabel挂到对象树上,析构函数确实被执行了,当窗口被销毁时,就会自动销毁对象树中的所有对象。但是预期的打印效果是“~MyLabel()对象释放”,实际出现了乱码。

2.2、乱码问题

出现乱码的原因只有一个就是编码方式不匹配。如果字符串本身是utf8编码的,但是终端(控制台)是按照GBK的方式来进行解析显示的,此时就会出现乱码。

表示汉字的字符集是有很多种的,不同的字符集表示同一个汉字,使用的数字不同,目前表示汉字字符集,主要是两种方式:

1、GBK:使用两个字节来表示一个汉字。

2、UTF-8(utf8):是变长编码,表示一个符号,使用的字节数有变化。在UTF-8中一个汉字一般占三个字节。(当前表示中文的主流方式还是UTF-8)

字符串使用的编码方式是和当前的mylabel.cpp文件的编码方式是一样的。

通过使用记事本打开mylabel.cpp文件,可以看到如下内容:

说明采用的是UTF-8的编码。如果显示的是ANSI则说明这个文件是GBK编码。既然终端出现了乱码,也就说明了终端不是按UTF-8的方式来显示字符串的。

Qt中的QString是可以帮助我们自动处理编码方式的,此外,Qt还提供了专门打印日志的工具,也能自动的处理编码方式。Qt中提供了一个qDebug工具,借助这个工具,就可以完成打印日志的过程,可以很好的处理字符编码。例如:

运行结果为:

我们可以看到此时就可以正确的进行打印了。使用这个qDebug还有一个好处就是可以通过编译开关实现一键式关闭。

Qt内置的QLabel,没法看到销毁的过程,为了看清楚销毁的过程,所以创建了类MyLabel,该类继承了QLabel,写了析构函数,在析构函数中,加上了日志,因此就可以直观的看到对象的释放过程了。(还可以重写其他功能,不仅仅是析构函数,从而达到功能扩展的目的)。

注:在Qt中,尽量在构造的时候就指定parent对象,并且大胆在堆上创建。

3、多种方式实现

除了上面的使用标签的方式实现hello world外,完成hello world是可以使用多种方式的。

3.1、使用编辑框实现

3.1.1、使用图形化的方式

编辑框有两种类型,一种是单行编辑框(line Edit),另一种是多行编辑框(Text Edit)。如下图所示:

我们使用单行编辑框实现,如下:

点击运行,结果为:

3.1.2、使用纯代码的方式

例如:

运行结果为:

3.2、使用按钮实现

3.2.1、使用图形化方式

我们使用下面的这个控件来实现hello world,如下:

例如:

运行结果为:

作为一个按钮,它的最主要的作用就是可以点击,不过当前点击该按钮是没有任何反应的,要想让按钮被点击后出现一定的效果,就需要用到Qt中的信号和槽,本质上就是给按钮关联上一个处理函数,当用户点击时,就会执行这个处理函数。

Qt中的connect函数是QObject这个类提供的静态函数,这个函数的作用就是连接信号和槽,该函数需要四个参数,第一个参数描述的是谁发出的信号,第二个参数描述了发出了什么样的信号,第三个参数描述了谁来处理这个信号,第四个参数描述了如何处理这个信号。如下图所示:

其中第一个参数指向的就是form file文件中创建的控件,在Qt Designer中创建一个控件时,就会给该控件分配一个objectName属性,这个属性的值要求是唯一的,对于该属性的值,我们也可以手动的进行修改(后面根据.ui文件生成C++代码,该C++代码中QPushButton对象的变量名字就是这里的objectName的值)。如下图所示:

对于第二个参数,表示点击该按钮时,触发该信号。

第三个参数表示当前的Widget来处理这个信号。

第四个参数表示处理函数是handlerClick。

例如:

Widget.h:

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void handlerClick();private:Ui::Widget *ui;
};
#endif // WIDGET_H

Widget.cpp:

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(ui->pushButton, &QPushButton::clicked, this, &Widget::handlerClick);
}Widget::~Widget()
{delete ui;
}void Widget::handlerClick()
{// 当按钮被点击时,把按钮中的文本进行切换。if(ui->pushButton->text() == QString("hello world")) // test函数是用来获取按钮中的内容的。{ui->pushButton->setText("hello Qt");}else{ui->pushButton->setText("hello world");}
}

运行结果为:

当进行点击时,按钮中的文本就会发生替换。

我们可以打开ui_widget.h文件来看一下,其中的代码就包含一个QPushButton的成员变量,这个变量的名字就是根据objectName来确定的。例如:

后面Widget会继承Ui_Widget,因此就可以通过Widget中的ui来访问pushButton这个变量了。

3.2.2、使用纯代码的方式

widget.h:

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QPushButton>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void handlerClick();private:Ui::Widget *ui;QPushButton* myButton;
};
#endif // WIDGET_H

widget.cpp:

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);myButton = new QPushButton(this);myButton->setText("hello world");connect(myButton, &QPushButton::clicked, this, &Widget::handlerClick);
}Widget::~Widget()
{delete ui;
}void Widget::handlerClick()
{if(myButton->text() == QString("hello world")){myButton->setText("hello Qt");}else{myButton->setText("hello world");}
}

运行结果为:

点击按钮也是可以起到文本的替换的。

3.3、图形化和纯代码对比

在实际的开发中,无论是纯代码的方式还是图形化的方式都是很重要的。

如果要写的程序的界面是比较固定的话,此时往往就会以图形化的方式来构造界面。

如果要写的程序的界面经常要动态变化,此时往往就会以代码的方式构造界面。

总的来说,哪一个比较方便就使用哪一个。另外这个两种方式并不是冲突的,是可以互相配合使用的。

4、Qt中的注意事项

4.1、命名规范

类名:首字母大写,单词和单词之间首字母大写(大驼峰)。

函数名及变量名:首字母小写,单词和单词之间首字母大写(小驼峰)。

注:Qt偏好驼峰命名法,而不是蛇形命名法(例如:student_count)。另外,驼峰命名法又可以分为两种,一个是小驼峰还有一个是大驼峰,小驼峰就是首字母小写,大驼峰就是首字母大写。

4.2、快捷键

注释:ctrl + /

运行:ctrl + R

编译:ctrl + B

字体缩放:ctrl + 鼠标滑轮

查找:ctrl + F

帮助文档:F1

同名之间的.h和.cpp文件之间的切换:F4。

生成函数声明的对应定义:alt + enter(也就是写完一个函数声明后,按下该快捷键,就可以自动的在对应的.cpp文件中添加函数的定义了)。

4.3、使用帮助文档

打开帮助文档有三种方式,实际编程中使用哪种都可以。

1、光标放到要查询的类名或方法名上,直接按F1。

2、Qt Creator左侧边栏中直接用鼠标单击"帮助"按钮:

点击"帮助"之后,出现如下图示界面:

然后我们就可以在上面这个界面中进行查找了。

3、找到Qt Creator的Assistant,如下图:

然后双击打开:

然后我们就可以在上面这个界面中进行查找了。

5、Qt窗口坐标系

坐标体系:以左上角为原点(0,0),X向右增加,Y向下增加。如下图所示:

对于嵌套窗口,其坐标是相对于父窗口来说的。

坐标的单位是像素,比如:以我当前的使用的显示器为例

上面图片的含义是水平方向的长度上有2560个像素点,垂直方向上的长度上有1440个像素点。

例如:使用Qt中的坐标系设置控件的位置;

widget.cpp:

#include "widget.h"
#include "ui_widget.h"#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* myButton = new QPushButton(this);myButton->setText("按钮");myButton->move(200,300); // move函数可以用来设置位置
}Widget::~Widget()
{delete ui;
}

运行结果为:

注意:

如果我们想要Widget的位置发生变化,例如:

widget.cpp:

#include "widget.h"
#include "ui_widget.h"#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* myButton = new QPushButton(this);myButton->setText("按钮");myButton->move(200,300); // 改变该控件在Widget中的位置this->move(100,0); // 改变窗口在屏幕中的位置
}Widget::~Widget()
{delete ui;
}

运行便会发现窗口的位置发生了变化。

http://www.dtcms.com/a/399425.html

相关文章:

  • APache shiro-550 CVE-2016-4437复现
  • 计算机视觉笔试选择题:题组2
  • 荣耀手机商城官方网站入口唐山网页设计
  • 凉山西昌网站建设网站公司可以做英文网吗
  • 软件开发转测试的过程中, UT测试如何体现
  • Si掺杂AlN薄膜在肖特基中的应用
  • 四种Linux进程管理工具使用详解
  • 软件的自动化测试平台
  • 分享天气预报走势图和未来7日预报静态HTML
  • 如何建立国际网站网站建设现状调查研究
  • JVM(六)-- StringTable
  • SpringBoot面试
  • 网站建设技术课程设计报告保定市网站制作公司
  • 如何处理JavaScript渲染的登录页面?Selenium自动化登录指南
  • 知识图谱对自然语言处理中深层语义分析的影响与启示
  • 齐齐哈尔企业网站排名优化网站建设设计制作熊掌号
  • 52Hz——FreeRTOS学习笔记——调度器的挂起与恢复
  • 微信网站建设平台郑州全面恢复正常
  • 8.Spring Ai Alibaba招聘助手实战
  • 平凉网站建设平凉杭州电信网站备案
  • 从GitHub下载单个文件夹的完整指南
  • 第二课强登陆网站新型智库建设的意见OA网站建设分析
  • Dify本地化部署和应用
  • 公司网站怎么做才能有官网二字做外贸网站那个平台好
  • linux docker 数据迁移
  • 自动点击器助手 1.1.5 | 支持免root录制点击脚本,一键录制重复点击脚本
  • qwen2.5-vl多模态大模型详解
  • 如何做好一个网站深圳网站和app建设
  • Linux进程概念(1)
  • w32time 服务