当前位置: 首页 > 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.dtcms.com/a/291683.html

相关文章:

  • MatterPort3D 数据集 | 简介 | 多途径下载
  • Aspose.Cells 应用案例:法国能源企业实现能源数据报告Excel自动化
  • UE创作一个可以变更列数的万能表格
  • Excel file format cannot be determined, you must specify an engine manually.
  • 如何撤销Git提交误操作
  • 实用资源分享:50款出入库单据Excel模板集合
  • DFS习题篇【下】
  • 北京养老金计算公式网页实现案例:从需求分析到架构设计
  • 业务流逻辑如何搭建?为何橙武平台选用了 LogicFlow?
  • 【MyBatisPlus】一文讲清 MyBatisPlus 基本原理及基本使用方式
  • EMA《2025-2028年药品监管中的数据与AI 1.3版》信息分析
  • 深度分析:Kimi K2开源模型
  • 拆分、合并PDF
  • Qt基本控件使用:按钮、标签、文本框等
  • docker阿里云安装
  • [2025CVPR]ViKIENet:通过虚拟密钥实例增强网络实现高效的 3D 对象检测
  • AI Agent-Manus 构建经验解读(下)
  • powerquery如何实现表的拼接主键
  • mybatis多对一一对多的关联及拼接操作以及缓存处理
  • Java 与 Android 回收机制深度解析
  • 行业出海研究报告
  • Apache Ignite 中的 SQL 模式(Schema)管理机制
  • Qt字符串处理与正则表达式应用
  • MCP vs 传统集成方案:REST API、GraphQL、gRPC的终极对比
  • 使用vue-pdf-embed发现某些文件不显示内容
  • Jenkins接口自动化测试(构建)平台搭建
  • Jenkins 多架构并发构建实战
  • 计算机网络:连接世界的数字脉络
  • Python爬虫实战:研究pymorphy2库相关技术
  • JVM:工具