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

【Qt开发】Qt的背景介绍(四)

目录

1 -> Qt Hello World 程序

1.1 -> 使用“按钮”实现

1.1.1 -> 纯代码方式实现

1.1.2 -> 可视化操作实现

1.2 -> 使用“标签”实现

1.2.1 -> 纯代码方式实现

1.2.2 -> 可视化操作实现

2 -> 项目文件解析

2.1 -> .pro文件解析

2.2 -> widget.h文件解析 

2.3 -> main.cpp文件解析

2.4 -> widget.cpp文件解析

2.5 -> widget.ui文件解析

3 -> Qt 编程注意事项

3.1 -> Qt 中的命名规范

3.2 -> Qt Creator 中的快捷键

3.3 -> 使用帮助文档

3.4 -> 认识对象模型(对象树)

3.5 -> Qt 窗口坐标体系


1 -> Qt Hello World 程序

1.1 -> 使用“按钮”实现

1.1.1 -> 纯代码方式实现

实现效果如下:

1.1.2 -> 可视化操作实现

1. 双击“widget.ui”文件

2. 拖拽控件至ui界面窗口并修改内容

3. 构建并运行,实现效果如下:

1.2 -> 使用“标签”实现

1.2.1 -> 纯代码方式实现

实现效果:

1.2.2 -> 可视化操作实现

1. 双击“widget.ui”文件

2. 拖拽“标签”至ui设计界面中,并双击修改标签内容

3. 实现效果如下

2 -> 项目文件解析

2.1 -> .pro文件解析

工程新建好之后,在工程目录列表中有⼀个后缀为 ".pro" 的文件, ".pro" 文件就是工程文件 (project),它是 qmake 自动生成的用于生产 makefile 的配置文件。如图所示:

双击进⼊该文件,该文件的核心内容如下:
QT += core gui // Qt 包含的模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //大于 Qt4 版本才包含 widget 模块
TARGET = QtFirst //应用程序名生成的 .exe 程序名称
TEMPLATE = app //模板类型,应用程序模板
SOURCES += main.cpp\ //源文件
widget.cpp //源文件
HEADERS += widget.h //头文件
".pro" 文件的写法如下:
1. 注释:从 "#" 开始,到这⼀行结束。
2. QT += core gui // Qt 包含的模块 Qt5 包含的模块如下图所示:

3. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 这条语句的含义是,如果QT_MAJOR_VERSION 大于 4 也就是当前使⽤的 Qt5 及更高版本) 需要增加 widgets 模块。如果项目仅需支持 Qt5 , 也可以直接添加 "QT += widgets" ⼀句。不过为了保持代码兼容 ,最好还是按照 QtCreator 生成的语句编写。
4. 指定生成的应用程序名:TARGET = QtDemo
5. TEMPLATE = app //模板。告诉 qmake 为这个应用程序生成哪种 makefile。下面是可供选择的模板:
  • app:建立⼀个应⽤程序的 makefile。这是默认值,所以如果模板没有被指定,这个将被使 用。
  • lib :建立⼀个库的 makefile。
  • vcapp:建立⼀个应用程序的 VisualStudio 项目文件。
  •  vclib: 建立⼀个库的 VisualStudio 项目文件。
  • subdirs:这是⼀个特殊的模板,它可以创建⼀个能够进⼊特定目录的 makefile 并且为它调用make 的 makefile。
6. 工程中包含的源文件:SOURCES += main.cpp/widget.cpp
7. 工程中包含的头文件:HEADERS += widget.h
8. 工程中包含的资源文件:RESOURCES += painter.qrc
9. 工程中包含的 "ui" 设计文件:FORMS += widget.ui
10. 配置信息:CONFIG += c++11 (使用 c++11 的特性) CONFIG 用来告诉 qmake 关于应用程序的配置信息。

2.2 -> widget.h文件解析 

在Qt中,如果要使用信号与槽(signal 和 slot)的机制 就必须加入 Q_OBJECT 宏;
Ui::Widget *ui; 这个指针是用前面声明的 namespace Ui 里的 Widget 类定义的,所以指针 ui 是指向可视化设计的界面,后⾯要访问界面上的组件,都需要通过这个指针 ui 去访问。

2.3 -> main.cpp文件解析

使用Qt Creator新建任意工程之后,main.cpp文件中都会自动生成如下代码:

解释:

1. Qt 系统提供的标准类名 声明头文件没有 .h 后缀;
2. Qt ⼀个类对应⼀个头文件,类名 就是 头文件名;
3. QApplication 为应用程序类;QApplication a;(a为应用程序对象,有且仅有⼀个。)
  • QApplication 管理图形用户界面应用程序的控制流和主要设置。
  • QApplication 是 Qt 的整个后台管理的命脉。它包含主事件循环,在其中来自窗口系统和其它 资源的所有事件处理和调度。它也处理应用程序的初始化和结束,并且提供对话管理。
  • 对于任何⼀个使用 Qt 的图形用户界面应用程序,都正好存在⼀个 QApplication 对象,而不论 这个应用程序在同⼀时间内是不是有 0、1、2 或更多个窗⼝。
4. myWidget w; //实例化窗口对象
5. w.show(); //调用show函数显示窗口
6. a.exec() :程序进⼊消息循环,等待对用户输入进行响应。这里 main()把控制权转交给Qt,Qt 完成事件处理工作,当应用程序退出的时候 exec() 的值就会返回。在 exec() 中,Qt 接受并处理用户和系统的事件并且把它们传递给适当的窗口部件。

2.4 -> widget.cpp文件解析

widget.cpp 文件是类 Widget 的实现代码,所有的窗体上要实现的功能添加在此文件中

2.5 -> widget.ui文件解析

widget.ui 是窗体界面定义文件,是⼀个 XML 文件,定义了窗口上的所有组件的属性设置、布局,及其信号与槽函数的关联等。用 UI 设计器可视化设计的界面都由 Qt 自动解析,并以 XML 文件的形式保存下来。在设计界⾯时,只需在 UI 设计器里进行可视化设计即可,而不用管 widget.ui 文件是怎么生成的。

3 -> Qt 编程注意事项

3.1 -> Qt 中的命名规范

  • 类名:首字母大写,单词和单词之间的首字母大写
  • 函数名及变量名:首字母小写,单词和单词之间首字母大写

Qt 偏好驼峰命名法,这点不同于C/C++偏好蛇形命名法。

3.2 -> Qt Creator 中的快捷键

  • 注释:ctrl + /
  • 运行:ctrl + R
  • 编译:ctrl + B
  • 字体缩放:ctrl + 鼠标滚轮
  • 查找:ctrl + F
  • 整行移动:ctrl + shift + ⬆/⬇
  • 帮助文档:F1
  • 自动对齐:ctrl + i
  • 同名之间的 .h 和 .cpp 的切换:F4
  • 生成函数声明的对应定义:alt + enter

3.3 -> 使用帮助文档

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

1. 光标要放到要查询的类名/方法名上,直接按F1

2. Qt Creator 左侧边栏中直接用鼠标单击“帮助”按钮

点击“帮助”之后,出现如下界面:

3. 找到 Qt Creator 的安装路径,在“bin”文件夹下找到 assistant.exe,双击打开

使用示例

1. 新建项目,在新建项目中使用 Qt 中的“QPushButton”控件

2. 打开帮助手册,在“索引”里面输入“QPushButton”

3.4 -> 认识对象模型(对象树)

在 Qt 中创建很多对象的时候会提供⼀个 Parent 对象指针,下⾯来解释这个 parent 到底是⼲什么的。
1. QObject 是以对象树的形式组织起来的。 
  • 当创建⼀个 QObject 对象时,会看到 QObject 的构造函数接收⼀个 QObject 指针作为参数,这个参数就是 parent,也就是⽗对象指针。
  • 这相当于,在创建 QObject 对象时,可以提供⼀个其⽗对象,我们创建的这个 QObject 对象会⾃动添加到其⽗对象的 children() 列表。
  • 当⽗对象析构的时候,这个列表中的所有对象也会被析构。(注意,这⾥的⽗对象并不是继承意义上的⽗类!)

这种机制在 GUI 程序设计中相当有⽤。例如,⼀个按钮有⼀个 QShortcut(快捷键)对象作为其 ⼦对象。当删除按钮的时候,这个快捷键理应被删除。这是合理的。

2. QWidget 是能够在屏幕上显⽰的⼀切组件的⽗类。
  • QWidget 继承⾃ QObject ,因此也继承了这种对象树关系。⼀个孩⼦⾃动地成为⽗组件的⼀ 个⼦组件。因此,它会显⽰在⽗组件的坐标系统中,被⽗组件的边界剪裁。例如,当⽤⼾关闭 ⼀个对话框的时候,应⽤程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该 ⼀起被删除。事实就是如此,因为这些都是对话框的⼦组件。
  • 当然,我们也可以⾃⼰删除⼦对象,它们会⾃动从其⽗对象列表中删除。⽐如,当我们删除了 ⼀个⼯具栏时,其所在的主窗⼝会⾃动将该⼯具栏从其⼦对象列表中删除,并且⾃动调整屏幕 显⽰。

Qt 引⼊对象树的概念,在⼀定程度上解决了内存问题。

  • 当⼀个 QObject 对象在堆上创建的时候,Qt 会同时为其创建⼀个对象树。不过,对象树中对象的 顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。
  • 任何对象树中的 QObject 对象 delete 的时候,如果这个对象有 parent,则⾃动将其从 parent 的 children() 列表中删除;如果有孩⼦,则⾃动 delete 每⼀个孩⼦。Qt 保证没有 QObject 会被 delete 两次,这是由析构顺序决定的。
如果 QObject 在栈上创建,Qt 保持同样的⾏为。正常情况下,这也不会发⽣什么问题。来看下⾯的代码⽚段:

作为⽗组件的 window 和作为⼦组件的 quit 都是 QObject 的⼦类(事实上,它们都是QWidget的⼦类,⽽QWidget 是 QObject 的⼦类)。这段代码是正确的,quit 的析构函数不会被调⽤两次,因为标准 C++ 要求,局部对象的析构顺序应该按照其创建顺序的相反过程。因此,这段代码在超出作⽤域时,会先调⽤ quit 的析构函数,将其从⽗对象 window 的⼦对象列表中删除,然后才会再调⽤window 的析构函数。
但是,如果我们使⽤下⾯的代码:

情况⼜有所不同,析构顺序就有了问题。我们看到,在上⾯的代码中,作为⽗对象的 window 会⾸先被析构,因为它是最后⼀个创建的对象。在析构过程中,它会调⽤⼦对象列表中每⼀个对象的析构函数,也就是说, quit 此时就被析构了。然后,代码继续执⾏,在 window 析构之后,quit 也会被析构,因为 quit 也是⼀个局部变量,在超出作⽤域的时候当然也需要析构。但是,这时候已经是第⼆次调⽤ quit 的析构函数了,C++ 不允许调⽤两次析构函数,因此,程序崩溃了。
由此我们看到,Qt 的对象树机制虽然在⼀定程度上解决了内存问题,但是也引⼊了⼀些值得注意的事情。这些细节在今后的开发过程中很可能时不时跳出来烦扰⼀下,所以,我们最好从开始就养成良好习惯。

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

Qt 对象树如图

代码示例

1. 创建一个新工程并编译运行,生成如下窗口

2. 选中工程名,鼠标右键 => “add new……”(或者“添加新文件”)

3. 选择“choose……”,弹出如下界面

4. 点击“下一步”,弹出如下对话框

5. 点击“完成”之后,手动创建类的头文件以及源文件会自动添加到目标工程中

6. 修改头文件

7. 编写源文件

8. 编译并运行

9. 当关闭弹出的对话框时,就会自动调用按钮的析构函数

10. 观察析构函数的执行顺序

11. 执行结果

12. 执行结果分析

对象树确保的是先释放子节点的内存,后释放父节点的内存。

而析构函数的调用顺序则不一定遵守上述要求,因此看到子节点的析构执行顺序反而在父节点析构顺序之后。

注意:

调用析构函数和释放内存并非是同一件事情。

3.5 -> Qt 窗口坐标体系

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

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

示例:使用 Qt 中的坐标系设置控件的位置。

运行结果如下:


感谢各位大佬支持!!!

互三啦!!!

http://www.xdnf.cn/news/1165861.html

相关文章:

  • 网络编程---网络基础知识
  • n8n - 为技术团队提供安全的自动化工作流
  • SpringMVC快速入门之启动配置流程
  • 双指针算法介绍及使用(上)
  • 哈希算法(Hash Algorithm)
  • 【bug】 jetson上opencv无法录制h264本地视频
  • Python编程进阶知识之第三课处理数据(numpy)
  • 学习pwn需要的基本汇编语言知识
  • MCP vs 传统集成方案:REST API、GraphQL、gRPC的终极对比
  • nodejs:告别全局安装,npx 命令详解及其与 npm 的区别
  • npm全局安装后,依然不是内部或外部命令,也不是可运行的程序或批处理文件
  • Go语言切片(Slice)与数组(Array)深度解析:避坑指南与最佳实践
  • rocky9-zabbix简单部署
  • Vue底层换成啥了?如何更新DOM的?
  • 基于单片机智能消毒柜设计
  • 【IDEA】如何在IDEA中通过git创建项目?
  • 原型链污染
  • uniapp请求封装上传
  • uniapp app打包流程
  • 【Python办公】Excel工作表拆分工具(按照sheet进行拆分-calamine-极速版)
  • NIO技术原理以及应用(AI)
  • Kotlin介绍
  • 重构创作边界:川翔云电脑 - UE5云端超算引擎​
  • Kafka——揭开神秘的“位移主题”面纱
  • Springboot+vue个人健康管理系统的设计与实现
  • 【电影剖析】千钧一发
  • ISPDiffuser文章翻译理解
  • 深入解析MIPI C-PHY (二)C-PHY三线魔术:如何用6种“符号舞步”榨干每一滴带宽?
  • uni-api交互反馈组件(showToast)的用法
  • SmartETL循环流程的设计与应用