目录

一.Qt SDK的下载安装

二.给装好的Qt配置一下环境变量

三.认识QtSDK中的重要工具

四.使用Qt创建一个空项目

4.1.创建空项目的全过程

4.2.认识QtCreator界⾯

4.2.1 左边栏

4.2.2.代码编辑区

4.2.3.UI设计界⾯

4.2.4.构建区

4.3.项目代码详解

4.2.1.main.cpp

4.2.2.widget.h和widget.cpp

4.2.3.widget.ui

4.2.4..pro ⽂件解析

五. QtHelloWorld程序

5.1.使⽤"标签"实现

5.1.1.可视化操作实现

5.1.1. 纯代码⽅式实现

5.2.使用输入框实现

5.2.1.可视化操作实现

5.2.2.纯代码方式实现

六.对象树

6.1.内存泄漏问题的讨论

6.2.对象树

6.3.对象树的缺点

七.实验:验证对象树内存释放过程

八. Qt编程注意事项

8.1 Qt中的命名规范

8.2 QtCreator中的快捷键

8.3.使用帮助文档

九.Qt窗⼝坐标体系


一.Qt SDK的下载安装

Qt下载官网:Index of /archive/qt

这个就是Qt SDK。


1、找到下载的⽂件并双击;注意:在双击之前先断⽹,否则需要我们注册Qt账号登录后才能进⼊下 ⼀步安装;

选择安装路径时不能出现中⽂路径,否则即使安装上也⽆法使⽤;

注意:上面这3个选项一定要选。

注意一定要取消上面这个。

二.给装好的Qt配置一下环境变量

首先我们找到Qt的安装路径,复制 "bin" 路径;

我这里的bin路径就是D:\Qt\5.14.0\mingw73_64\bin

接着我们点击"此电脑"------> ⿏标右键,"属性"------>"⾼级系统设置"------> "环境变量"

接着我们按照下面这个来操作即可

我们把这个bin目录的路径给复制进去。

一定要点确定!!!!要不然我们作的修改都是没有用的。

三.认识QtSDK中的重要工具

我们去开始菜单看看

这些就是Qt SDK自带的一些工具程序,也都是我们在开发中需要关注的。

Assistant 5.14.0 (MinGW 7.3.0 64-bit)

  • 是什么:Qt 助手,也就是 Qt 的官方文档浏览器

  • 干什么用

    • 它是一个功能强大、离线可用的帮助文档系统。

    • 包含了所有 Qt 模块、类、函数、示例和教程的详细说明。

    • 是开发者在编程过程中查阅 API、学习如何使用 Qt 功能的最重要工具。

    • 通常可以在 Qt Creator 中按 F1 键直接调出相关条目的帮助。

我们看看

可以看到里面都是一些教程啊。

Designer 5.14.0 (MinGW 7.3.0 64-bit)

  • 是什么:Qt 设计师,一个 可视化的 GUI 界面设计工具

  • 干什么用

    • 通过拖放按钮、文本框、列表等控件来设计应用程序的窗口、对话框等界面。

    • 设计好的界面会保存为后缀名为 .ui 的 XML 文件。

    • 开发者无需手动编写大量构建界面的代码,Qt 可以在编译时或运行时自动加载这些 .ui 文件来生成界面。

    • 极大地提高了图形界面开发的效率。

Linguist 5.14.0 (MinGW 7.3.0 64-bit)

  • 是什么:Qt 语言家,一个 软件国际化 (i18n) 和本地化 (l10n) 工具

  • 干什么用

    • 帮助开发者轻松地将应用程序翻译成多种语言。

    • 工作流程是:开发者使用 tr() 标记代码中需要翻译的文本 -> 使用 Qt 工具提取这些文本生成 .ts 翻译源文件 -> 翻译人员用 Linguist 打开 .ts 文件进行翻译 -> 翻译完成后发布为 .qm 文件(压缩的二进制翻译文件)。

    • 应用程序运行时根据系统语言加载对应的 .qm 文件,即可显示相应的语言界面。

Qt 5.14.0 (MinGW 7.3.0 64-bit)

  • 是什么:这是 Qt 库本身的核心组件,而不是一个单独的工具。

  • 干什么用

    • 它代表了你安装的 Qt 开发库的版本(5.14.0)、所用的编译器(MinGW 7.3.0)和平台(64-bit)。

    • 你的应用程序需要链接这个库才能运行。它包含了所有核心的 GUI 和非 GUI 功能模块(如网络、数据库、多媒体、XML处理等)。

    • 在开始菜单里点击它通常不会打开一个程序,它可能是一个指向 Qt 安装目录的快捷方式,或者是一个环境配置的脚本。

Qt Creator 4.11.0 (Community)

  • 是什么:这是 官方的集成开发环境 (IDE),是进行 Qt 开发的主战场。

  • 干什么用

    • 代码编辑器:提供语法高亮、代码补全、错误检查等功能。

    • 项目管理:可以创建、打开、构建和运行 Qt 项目(以及普通的 C++ 项目)。

    • 图形化调试器:集成强大的调试功能,可以设置断点、查看变量、单步执行等。

    • 可视化设计:集成了 Qt Designer 的功能,可以在 IDE 内直接拖拽设计界面。

    • 版本控制集成:支持 Git、SVN 等。

    • 它是一个功能完整的 IDE,你将在这里花费绝大部分的开发时间来编写代码、设计和调试。

四.使用Qt创建一个空项目

4.1.创建空项目的全过程

项目模板 说明
Application Qt 应用程序,包括普通窗体程序和QtQuick程序
Library 可以创建动态库、静态库以及QtQuick扩展插件、QtCreator自身插件
其他项目 可以创建单元测试项目、Qt4设计师自定义控件、子目录项目等
Non-Qt-Project 非Qt项目。可以创建纯C或纯C++项目
Import Project 导入项目。从版本控制系统管理的软件项目导入旧的项目

常用的只有第一类Application,选择它,在右侧会看到Qt应用程序的五个子模板:

  • Qt Widgets Application:普通窗体模板,传统基于部件的窗体界面程序。

  • Qt Console Application:Qt控制台应用程序。因为Qt主要用于图形界面设计,这个控制台项目模板基本不用。

  • Qt for Python:在Python下用LGPL的许可来开发闭源Qt软件。

  • Qt Quick Application:Qt提供的一种高级用户界面技术,使用它可以方便快速的为移动以及嵌入式设备开发流畅美观的用户界面。QtQuick模块是开发QML应用的标准库,提供了使用QML创建用户界面所需的一切,包括可视化、交互、动画、模型、视图、粒子效果以及着色效果等。

注意这里的项目名和项目存储路径一定不能带有中文!!!!否则无法使用。

Qt 中的构建⼯具有三种可供选择,分别是:qmake、CMake、Qbs,下⾯依次介绍。

  1. qmake:qmake是⼀个构建⼯具(buildtool),⽤于⾃动⽣成makefile⽂件。qmake⽀持跨平 台构建。qmake编辑的是⼀个后缀名为.pro的⽂件。
  2. CMake:CMake是⼀个跨平台的构建⼯具。CMake本⾝不是⼀个编译器,其实就是⽣成⼀个让编 译器能读懂编译流程的⽂件⼯具。让CMake⾃动⽣成构建系统,例如Makefile和VisualStudio 项⽬⽂件。CMake是⼀个第三⽅⼯具,有⾃⼰的⽂档。
  3. Qbs:Qbs(QtBuildSuite:Qt构建套件)同qmake、CMake⼀样都是构建⼯具。Qbs号称是新 ⼀代的构建⼯具,⽐qmake编译速度更快。Qbs没有绑定Qt版本,它从项⽬⽂件的⾼级项⽬描述 中⽣成⼀个正确的依赖表。⽽传统的MakeFile⽣成⼯具如qmake和CMake,其在⽣成MakeFile ⽂件后将实际的命令交给Make⼯具去执⾏。

Qt官⽅声明,因市场原因,弃⽤Qbs。对于Qt⽤⼾来说,qmake是当前使⽤最⼴泛的构建⼯具, CMake其次。

选择Qt项⽬的构建系统,使⽤默认的"qmake" 即可。我们直接点击下一步

创建 Qt Widgets Application 时,需要为主窗口选择一个基类。这三种基类有各自明确的用途,选择合适的基类是构建应用程序的第一步。

基类 说明 主要用途与特点 典型场景
QMainWindow 主窗口类,提供了一个典型的应用程序主窗口框架。 用于构建复杂的桌面应用程序。它预定义了菜单栏工具栏状态栏以及一个中央部件区域,还可以包含多个可停靠的** dock Widget**(工具面板)。您只需将自定义的界面内容设置到中央部件即可。 大型软件如 IDE(Qt Creator、Visual Studio)、图像处理软件(GIMP、Photoshop)、办公软件等。
QWidget 最简单、最通用的窗口基类。 作为顶级窗口子部件使用。当作为窗口时,它是最基础的空白窗体,没有任何预置的界面元素,为您提供了最大的灵活性。所有其他窗口部件都直接或间接继承自它。 简单的工具程序、自定义对话框、应用程序中的子面板、嵌入式设备的界面,或者任何不需要复杂框架结构的窗口。
QDialog 对话框类,继承自 QWidget,专为对话框设计。 主要用于弹窗(如设置对话框、关于对话框、文件选择框),也可以作为应用程序的主界面。它丰富了 QWidget 的功能,最核心的是支持模态(阻塞后台窗口)/非模态显示,并且可以提供对话框返回值(如 Ok/Cancel)。 登录窗口、偏好设置窗口、消息提示框、文件打开/保存对话框等。

总结与选择建议:

  • 开发复杂的桌面应用,需要菜单、工具栏等标准元素,选择 QMainWindow

  • 需要一个弹窗与用户进行交互,或者一个简单的工具窗口,选择 QDialog

  • 需要最大程度的自定义,或者创建一个将来要嵌入到其他界面中的部件,选择 QWidget。它是万能的基石。

它们3个的关系如下图

接着往下看

此处选择的语⾔是"汉语","英语"这样的语⾔.⽽不是"编程语⾔".

这个是有关国际化的东西,我们暂时用不到。

这个是选择一下基于哪个编译器的Qt SDK来构建后续代码。

默认只有第⼀个"DesktopQt5.14.0MinGW64-bit",如果安装配置了多个Qt套件,就可以都选上。 Qt 套件是指Qt程序从编译链接到运⾏环境的全部⼯具和Qt类库的集合,对于MinGW版本Qt程序⽣ 成和调试,⾄少需要MinGW中的编译器g++(⾃动调⽤链接器)、g++配套的基础库、调试器gdb还 有使⽤MinGW环境编译⽽成的Qt类库⾃⾝。

默认情况下,在上⾯KitSelection⾥选中全部套件。

我们这里只有一个选项,其实这个是和我们安装的时候是有关的。

点击"下⼀步"进⼊项⽬管理界⾯;在项⽬管理界⾯可以设置作为⼦项⽬,以及加⼊版本控制系统管 理。这两个功能暂时⽤不到,都⽤默认的,然后点击"完成"。

如 果想把代码提交到码云或者github,可以在此处选择git作为版本控制系统.

我们现在来运行一下程序。我们点击左下角的这个运行按钮

运行之后,就会弹出一个弹窗

里面什么都没有。

4.2.认识QtCreator界⾯

4.2.1 左边栏

在编辑模式下,左边竖排的两个窗⼝叫做"边栏"。

  • ①是项⽬⽂件管理窗⼝,
  • ②是打开⽂件列表窗⼝。

在QtCreator菜单"控件"------->"ShowLeftSidebar",或者使⽤快捷键:"Alt+0" 可以控制边栏的 显⽰和隐藏。

边栏⾥的窗⼝数⽬可以增加,边栏⼦窗⼝标题栏有⼀排⼩按钮,最右边的是关闭按钮,倒数第⼆个是 增加分栏按钮,可以添加多个边栏⼦窗⼝。

边栏⼦窗⼝标题栏第⼀个控件是组合框,可以选择该⼦窗⼝的功能视图类型,⽬前可以选择8个视图 类型:

视图名称 (View Name) 主要功能说明 (Description) 补充说明与使用场景 (Additional Notes & Use Cases)
项目 (Project) 管理项目文件的核心视图。可以浏览、选择、添加或移除项目中的文件,并对其进行编辑。支持直接手动编辑 .pro (Qt项目文件) 等配置文件。 这是项目的“总控制台”,用于管理项目的组成结构。手动编辑.pro文件常用于添加库链接、编译选项等高级配置。
打开文档 (Open Documents) 以标签页形式显示当前所有已打开文件的列表。如果文件名右侧显示 * 号,则表示该文件已被修改但尚未保存。 方便用户在多个已编辑的文件之间快速切换。星号(*)是重要的视觉提示,提醒开发者保存以免丢失更改。
书签 (Bookmarks) 通过在代码编辑器的行号位置右击选择“切换书签”,可以在特定代码行添加标记。便于快速导航和跳转到关键代码位置。 在阅读或调试大型源代码文件时极其有用,可以标记重要函数、待办事项(TODO)或错误位置,实现精准跳转。
文件系统 (File System) 像一个内置的文件资源管理器,直接显示项目文件夹在磁盘上的实际文件和目录列表,不受项目配置文件的过滤影响。 当需要查看或操作未被纳入项目但存在于目录中的文件(如日志、资源文件)时,此视图非常实用。它与“项目”视图互为补充。
类视图 (Class View) 以树形结构智能地解析并展示项目中的所有类、结构体、命名空间,以及它们的成员(函数、变量)。按逻辑结构组织,而非文件结构。 快速了解项目架构的利器。无需打开文件即可查看类的所有成员,并能通过点击直接跳转到对应的定义位置。
Git Branches 查看和操作当前的Git分支。通常可以在此进行分支切换、创建新分支、合并等版本控制操作。 为版本控制提供了图形化界面,是团队协作和代码管理的核心视图之一。让开发者无需命令行即可高效管理代码版本。
大纲 (Outline) 动态显示当前活跃代码文件(如.cpp.h)的结构大纲,包括类、函数、变量等符号列表。 在阅读或编辑单个大型文件时,可以快速定位到文件内的任何一个函数或变量,极大提高代码浏览效率。
Tests 集成测试功能的管理和运行视图。通常用于显示测试套件、用例,并可以运行和调试单元测试,查看测试结果。 保证代码质量的重要工具。遵循测试驱动开发(TDD)时,会频繁使用此视图来运行和验证测试。
类型层次 (Type Hierarchy) 分析并可视化展示类与类之间的继承关系。可以查看一个类的所有基类(父类)和所有派生类(子类) 在面向对象编程中,用于理解复杂的类继承体系,对于代码分析和重构至关重要。
包含层次结构 (Include Hierarchy) 显示头文件之间的包含依赖关系。可以查看一个.h.cpp文件直接或间接包含了哪些文件,以及被哪些文件所包含。

4.2.2.代码编辑区

①和②:导航按钮"返回"和"前进",这与⽹⻚浏览器的前进和后退按钮类似,可以在之前浏览的多个 代码⽂件或⼀个代码⽂件⾥多个位置之间快速切换。

③:标识当前显⽰的⽂件是只读还是可写,⼀般都是可写的。

④:⽂件类型图标,当前显⽰⽂件的类型,这个控件其实是⼀个菜单按钮,点击可以弹出丰富的⽂件 处理功能菜单。

⑤:打开的⽂件名,可以在多个打开的⽂件之间选择切换,与边栏的"打开⽂档"视图是对应的。

⑥:关闭当前显⽰的⽂档。

⑦:为当前显⽰的⽂件添加额外的C++预处理指令,⼀般⽤不着。

⑧:选择符号,可以在当前显⽰的⽂件⾥多个函数、类、成员变量等之前快速切换,与边栏"⼤纲"视 图是对应的。

⑨:编辑区光标的⾏号和列号。

⑩:代码编辑区分栏,可以增加多个编辑器窗⼝,显⽰多个打开的⽂档或显⽰较⼤源码⽂件的多个位 置。

⾏⾸区:主要⽤来显⽰代码⾏号,以及调试断点标志和代码书签标志。右击⾏⾸区可以弹出右键菜 单,菜单⾥可以切换书签、编辑书签以及设置或取消断点。

同⼀⾏是既可以打断点也可以设置书签的,⼆者不冲突,其实它们根本就没关系。单击⾏号前⾯的浅 灰⾊空⽩区可以直接打断点,再次单击可以取消断点,另外也可以⽤快捷键F9设置或取消断点。代码 书签⼀般⽤右键菜单来设置,也可以⽤快捷键Ctrl+M设置或取消书签。

编辑区:写代码的区域。

4.2.3.UI设计界⾯

双击widget.ui⽂件,QtCreator会⾃动进⼊设计模式,可以对图形界⾯进⾏可视化编辑:

①:组件选择窗⼝。组件选择窗⼝分为多个组,如Layouts、Buttons、DisplayWidgets等,界⾯设 计的常⻅组件都可以在组件选择窗⼝中找到。

②:UI设计窗⼝。如果要将某个组件放置到该窗⼝上时,从组件选择窗⼝上拖放⼀个组件到窗体上即 可。

③:动作编辑窗⼝。动作编辑窗⼝包括ActionEditor以及Signals和Slots编辑器。ActionEditor主 要是⽤来新建Action,并且通过拖拽的动作,将新建好的Action添加到菜单栏和⼯具栏上;Signals 和Slots编辑器⽤于可视化地进⾏信号与槽的关联。

④:对象浏览窗⼝。⽤树状视图显⽰窗体上各组件之间的布局包含关系,视图有两列,显⽰每个组件 的对象名称(ObjectName)和类名称。

⑤:属性设置窗⼝。显⽰某个选中的组件或窗体的各种属性及其取值,可以在属性设置窗⼝⾥修改这 些属性的值

4.2.4.构建区

左下⻆⼀共有四个按钮,下⾯分别介绍⼀下:

  • 第⼀个按钮是选择构建项⽬使⽤的Qt套件和构建⽬标程序的类型(Debug或Release)。
  • 第⼆个是运⾏按钮,快捷键是Ctrl+R,如果还没构建项⽬或刚修改了代码,直接点击运⾏的话, QtCreator 会⾃动构建⽣成新的⽬标程序并运⾏。
  • 第三个是调试按钮,快捷键是F5。调试程序之前,QtCreator会⾃动构建⽣成最新的⽬标程序,并 进⼊调试模式。
  • 第四个是构建按钮,快捷键是Ctrl+B,只构建最新的⽬标程序,但不运⾏。 

对于第⼀个按钮,默认的是Debug,构建的是Debug类型的⽬标程序。

如果需要构建Release版⽬标 程序,点开左下⻆第⼀个按钮:

这⾥有三种构建模式: 

模式 说明
Debug 以"-g"模式编译,带着符号信息,优点是便于调试
Profile profile 则是在"Debug"和"Release"之间取⼀个平衡,兼顾性能和调试,可以类似的看做是性能更优⼜⽅便调试的版本。
Release "Release" 是经过优化之后,性能⽐"Debug"更上⼀个档次

上图是针对项⽬只⽤到单⼀Qt套件的,如果之前配置了多个Qt套件,看到的类似下图:

如果项⽬配置了多个可⽤的Qt套件,点开左下⻆第⼀个按钮后,会看到各个套件以及构建类型,如果 要切换Qt套件或构建类型,直接选中相应条⽬,然后点击运⾏按钮就⾏了。

如果构建和运⾏时没出 错,就会显⽰出构建好的⽬标程序界⾯。

4.3.项目代码详解

我们仔细观察一下这个空项目的结构。

4.2.1.main.cpp

默认生成的main.cpp程序是下面这样子的。

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

这都是啥意思呢?

#include "widget.h"
  • 作用:包含头文件。

  • 详细解释:这行代码将你自己创建的 Widget 类的头文件包含进来。当你创建项目时,Qt Creator 会自动生成这个 widget.h 文件和一个对应的 widget.cpp 文件。Widget 类是你程序的主窗口类,所有的按钮、文本框等控件都将放在这个窗口里。


#include <QApplication>
  • 作用:包含 Qt 框架的核心头文件。

  • 详细解释QApplication 是 Qt 中一个至关重要的类。它管理了整个应用程序的全局资源、设置,以及最核心的事件循环(Event Loop)。任何一个使用 Qt Widgets 模块的图形界面程序,都必须有且只有一个 QApplication 对象。


int main(int argc, char *argv[])
  • 作用:C/C++ 程序的入口函数。

  • 详细解释:所有的 C/C++ 程序都从 main 函数开始执行。argc 和 argv 是命令行参数。argc 是参数的数量(Argument Count),argv 是一个指针数组,指向具体的参数字符串(Argument Vector)。Qt 会使用这些参数来解析一些特定的启动选项,比如 -style 来设置应用程序的样式。


QApplication a(argc, argv);
  • 作用:创建 QApplication 对象。

  • 详细解释:这是整个程序中最关键的一行代码。它使用传入的命令行参数 argc 和 argv 来初始化一个名为 a 的 QApplication 对象。正如前面所说,这个对象管理着应用程序的生命周期和事件处理。没有它,你的程序就无法处理用户的任何输入(如点击鼠标、敲击键盘),也无法进行界面的重绘等。编写一个Qt的图形化界面程序,一定需要有QApplication对象!


Widget w;
  • 作用:创建你的主窗口对象。

  • 详细解释:这里实例化了一个 Widget 类的对象 w。这个 Widget 类是你从 QWidget(Qt 所有窗口控件的基类)继承而来的。此时,窗口已经在内存中创建了,但它还没有显示在屏幕上。


w.show();
  • 作用:显示窗口。

  • 详细解释调用 QWidget 类的 show() 方法,让你创建的 w 窗口变得可见。默认情况下,窗口是处于“显示”状态的。与之对应的方法是 w.hide(),调用它会使窗口隐藏(不可见)。你可以通过代码在程序运行过程中控制窗口的显示和隐藏。


return a.exec();
  • 作用:启动应用程序的事件循环,并进入阻塞状态。

  • 详细解释a.exec() 这行代码启动了 Qt 的心脏——事件循环(Event Loop)。从此,程序就开始正式运行了。

    • 事件循环是做什么的? 它是一个无限循环,不断地检查是否有事件发生。比如用户点击了一下按钮(MousePressEvent),移动了一下鼠标(MouseMoveEvent),或者窗口需要重新绘制一下(PaintEvent)。事件循环会捕获这些事件,然后将它们分发给相应的对象(比如 w 窗口或窗口里的按钮)去处理。

    • return 的作用a.exec() 会一直阻塞在这里,直到你关闭所有窗口(比如点击了窗口右上角的 X),或者调用了 QApplication::quit() 方法,事件循环才会结束。a.exec() 会返回一个整数值(通常是 0 表示成功退出),这个值就作为 main 函数的返回值,也就是整个程序的退出码。

注意这里的exec和Linux的exec是完全不一样,是没有任何关系的。只是名字恰好是一样的。

4.2.2.widget.h和widget.cpp

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

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);
}

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

接下来是命名空间声明和前置声明:

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

QT_BEGIN_NAMESPACE 和 QT_END_NAMESPACE 是 Qt 定义的宏。

它们的作用是确保 Ui::Widget 类在正确的命名空间内进行声明。

中间的 namespace Ui { class Widget; } 是一个前置声明,它告诉编译器 Ui 命名空间内有一个名为 Widget 的类,但无需立即提供其具体定义。

这有助于减少编译依赖,加快编译速度。


之后是核心的类定义部分:

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};

该类名为 Widget,它公有继承自 Qt 框架中的 QWidget 类。QWidget 是所有用户界面组件的基类,代表一个窗口或一个控件。

宏 Q_OBJECT 是 Qt 框架的核心之一。它看起来像一条语句,但实际上是一个宏。

在预处理阶段,它会被替换为一系列由 Qt 的元对象编译器(moc)处理的代码。这些生成的代码为类提供了以下关键能力:

  • 信号与槽(Signals & Slots):Qt 独创的对象间通信机制。

  • 属性系统:支持在运行时查询和设置对象属性。

  • 动态元信息:支持在运行时获取类的名称、方法、信号等信息。

如果某个类想要使用信号与槽机制,它就必须在类声明的开头处包含这个 Q_OBJECT 宏。


接下来是构造函数析构函数

Widget(QWidget *parent = nullptr);
~Widget();
  • 构造函数接收一个指向父窗口部件的指针 parent,默认值为 nullptr(即没有父对象)。在 Qt 的对象树模型中,当一个对象被指定为另一个对象的子对象时,父对象被销毁时会自动销毁其所有子对象,这极大地简化了内存管理。

  • 析构函数负责清理该对象占用的资源。


最后是私有成员变量:

private:
    Ui::Widget *ui;

这里声明了一个指针 ui,它指向 Ui 命名空间下的 Widget 类。

这个类是由 Qt Designer(UI 设计工具)自动生成的,它包含了你在设计界面时拖放的所有控件的布局和属性定义。

在 Widget 类的源文件(.cpp)中,通常会通过 ui->setupUi(this); 来构造这个界面,并将所有控件设置到当前窗口上。

4.2.3.widget.ui

form file是什么

大家注意到下面这个文件了吗

 这个就是我们所谓的form file.

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

我们直接双击ui文件,此时Qt Creator就会调用QtDesigner打开.ui文件,图形化的界面编辑器

我们再点击下面这个按钮

进入下面这个界面

这就是XML格式,也就是说.ui文件。

XML格式和html是一样的,都是用来展示图像的。

Qt 中使用 xml 文件就是去描述程序的界面是啥样的。 进一步的 qmake 会调用相关的工具, 依据这个 xml 文件生成一些 C++ 代码, 从而把完整的界面构造出来。

4.2.4..pro ⽂件解析

⼯程新建好之后,在⼯程⽬录列表中有⼀个后缀为".pro"的⽂件,".pro"⽂件就是⼯程⽂件(project) ,它是qmake ⾃动⽣成的⽤于⽣产 makefile 的配置⽂件。如图所⽰

我们点击进去看看

都是啥意思呢?

1. 核心模块声明

QT       += core gui
  • QT += ...: 这行指定你的项目需要哪些 Qt 模块

  • core: 这是 Qt 的核心模块,包含了所有其他模块都依赖的非 GUI 基础功能(如字符串处理、容器类、文件 I/O、事件循环等)。几乎所有 Qt 项目都需要它。

  • gui: 提供了图形用户界面(GUI)所需的基础类,例如窗口系统集成、事件处理、2D 图形、字体和图像等。任何有图形界面的应用都需要它。


2. 条件添加 widgets 模块

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
  • greaterThan(QT_MAJOR_VERSION, 4):: 这是一个 条件判断。它的意思是“如果 Qt 的主版本号大于 4”。

  • QT += widgets: 如果条件满足(即使用的是 Qt 5 或更高版本),则添加 widgets 模块。

  • 为什么需要这个? 在 Qt 4 时代,GUI 模块包含了 widgets(按钮、文本框等基础控件)。从 Qt 5 开始,widgets 被拆分成了一个独立的模块。这行代码确保了项目的向后兼容性。如果你用 Qt 5/6 编译,它会自动添加 widgets 模块;如果你(理论上)用 Qt 4 编译,它就不会添加,因为控件已经在 gui 模块里了。


3. 启用 C++11 标准

CONFIG += c++11
  • CONFIG: 这是一个变量,用于指定项目构建时的各种配置和选项。

  • c++11: 这个选项告诉编译器和 qmake,你的项目代码需要使用 C++11 语言标准 进行编译。现代 Qt 和 C++ 代码强烈依赖 C++11 的特性(如 lambda 表达式、智能指针、范围 for 循环等),所以这几乎是必备的。在更新的项目中,你可能会看到 c++17 甚至 c++20


4. 弃用警告定义

DEFINES += QT_DEPRECATED_WARNINGS
  • DEFINES: 这个变量用于在编译时设置预处理器宏(#define)。

  • QT_DEPRECATED_WARNINGS: 定义这个宏后,如果你的代码中使用了已被 Qt 标记为“废弃”的类或函数,编译器会在编译时产生警告。这有助于你及时发现并更新代码,避免使用未来版本可能会被移除的旧 API,保证项目的长期健康。


5. (注释掉的)禁用废弃 API

#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
  • 这是一个被注释掉(以 # 开头)的配置,所以它目前不会生效。

  • 如果取消注释,它的作用会更进一步:它不仅会警告,而是会直接导致编译失败(报错),如果你的代码使用了在 Qt 6.0.0 版本之前就被废弃的 API。

  • 这是一个更严格、更强制性的代码现代化手段,通常在新项目或当你决心全面升级代码时使用。


6. 项目源文件列表

SOURCES += \
    main.cpp \
    widget.cpp

HEADERS += \
    widget.h

FORMS += \
    widget.ui

这些行列出了构建项目所需的所有文件:

  • SOURCES: 指定所有的 C++ 源文件.cpp)。

    • main.cpp: 通常包含 main() 函数,是程序的入口。

    • widget.cpp: 是 widget.h 中声明的类的实现文件。

  • HEADERS: 指定所有的 C++ 头文件.h 或 .hpp)。

    • widget.h: 通常声明了你的主窗口类(例如 Widget 或 MainWindow)。

  • FORMS: 指定所有的 Qt Designer 界面文件.ui)。

    • widget.ui: 这是一个 XML 文件,由 Qt Designer 图形化界面设计工具创建和编辑。qmake 会调用 uic(用户界面编译器)工具将其转换为对应的 C++ 头文件(ui_widget.h)。


7. 部署规则(通常无需修改)

qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
  • 这部分定义了当你执行 make install 时,将可执行文件安装到目标系统的哪个路径

  • qnx: 和 else: unix:!android:: 这些是平台相关的条件判断

    • qnx: 如果是 QNX 操作系统,安装到 /tmp/$${TARGET}/bin

    • else: unix:!android:: 否则,如果是 Unix 类系统(如 Linux、macOS)并且不是 Android,则安装到 /opt/$${TARGET}/bin。($${TARGET} 会被替换为你的项目名称)。

  • 对于日常开发(尤其是在 Windows/macOS/Linux 上进行桌面开发),你几乎永远不会使用 make install,所以这部分可以忽略不计,保留默认即可。

五. QtHelloWorld程序

5.1.使⽤"标签"实现

5.1.1.可视化操作实现

进来之后,寻找左下角这个

我们左键拖着它到屏幕中间

把它放大

我们左键双击,然后输入下面这个字体

有的人可能觉得这个字体大小不好看,我们可以去右下角这里来调整

我们注意程序右上角也有一个这个

这不就是我们拖着进去的QLabel吗。

我们现在可以回去看看,我们发现widget.ui大变样了,我们所作的修改都存在这里了。

我们也能在里面看到我们的Hello World。

我们的Qt就会 进一步的 qmake 会调用相关的工具, 依据这个.ui文件生成一些 C++ 代码, 从而把完整的界面构造出来。

好了,现在我们就能去运行一下了

运行之后,我们可以去看看

我们进入上一级目录,进入下面这个目录

QT 中使用.ui文件就是去描述程序的界面是啥样的。 进一步的 qmake 会调用相关的工具,依据这个 .ui文件生成一些 C++ 代码, 从而把完整的界面构造出来。

这个ui_widget.h文件就是依据这个 .ui文件自动生成的 C++ 代码。

我们打开看看,里面的核心内容就是下面这些

怎么样,都是在描述整个界面的。

5.1.1. 纯代码⽅式实现

我们在里面添加代码

我们发现它不知道什么情况。

注意了,在Qt中,每一个类都有一个对应同名的头文件

#include <QLabel>

现在我们运行一下

这个用代码实现的虽然和上面可视化操作的位置大小形式有点不同,但是基本是一样的,至于大小位置形式,我们其实也可以通过代码来实现,只不过这不是我们这里的重点,我就不讲了。

  • 关于 Qt 字符串与容器的背景说明

        在 Qt 中设置控件显示的文本通常使用 setText() 方法。值得注意的是,Qt 诞生于 1991 年,那时 C++ 尚未形成统一标准,更没有像后来的“标准库”那样成熟的设施。当时字符串的处理通常依赖于 C 风格字符串(以 \0 结尾),或是早期不够完善的 C++ string 类。

为了提升开发体验,Qt 自行实现了一套基础类库,包括字符串类型 QString、动态数组 QVector、链表 QList、字典 QMap 等。这些类大大简化了开发流程,并逐渐演变为 Qt 框架的核心组成部分。

        尽管后来 C++ 标准逐渐完善,引入了 std::string 和各种容器类,但 Qt 中已有的这些基础类因其成熟稳定且与框架深度集成,仍被广泛使用。因此,在 Qt 开发中,我们既可以使用 C++ 标准库中的容器,也可以使用 Qt 提供的这一套容器类。

        值得注意的是,Qt 自身的 API 普遍使用 Qt 容器类(如 QString),因此在 Qt 项目中使用这些类会更加方便。此外,QString 与 std::string 之间可以轻松转换,且 QString 内置了对字符编码的处理,使用起来比 std::string 更加友好和强大。

5.2.使用输入框实现

5.2.1.可视化操作实现

我们先创建一个空项目

接下来我们将使用编辑框来实现hello World

  • 单行编辑框QLineEdit
  • 多行编辑框QTextEdit

我们现在使用单行编辑框即可

我们把它拖出来

把它放大

然后我们双击,输入

其实我们也可以通过右侧的属性框来进行修改的

我们点击运行

这个输入框里面我们其实是可以修改的,我们直接把World删掉,换成下面这个

这就是输入框。

5.2.2.纯代码方式实现

我们创建一个新的项目

我们点击运行

还是和我们预期的一样啊。

六.对象树

6.1.内存泄漏问题的讨论

不指定大家有没有注意到一个点

我们使用new之后,我们并没有使用delete来释放内存吗?

不delete不就出现了内存泄漏了吗?

其实,上述代码不会造成内存泄漏。

关键的奥秘就在这个this

this是啥啊?实际上就是指向了下面这个Widget对象w

那么问题就来了?

为什么在创建这个QLabel对象的时候需要给他传递一个Widget对象?

这就涉及到我们的对象树的问题了。

6.2.对象树

在Qt中创建很多对象的时候会提供⼀个Parent对象指针,下⾯来解释这个parent到底是⼲什么的。

QObject是以对象树的形式组织起来的。

  • 当创建⼀个QObject对象时,会看到QObject的构造函数接收⼀个QObject指针作为参数,这个参数就是parent,也就是⽗对象指针
  • 这相当于,在创建QObject对象时,可以提供⼀个其⽗对象,我们创建的这个QObject对象会⾃动添加到其⽗对象的children()列表。
  • 当⽗对象析构的时候,这个children()列表中的所有对象也会被析构。(注意,这⾥的⽗对象并不是承意义上的⽗类!)

这种机制在GUI程序设计中相当有⽤。

例如,⼀个按钮有⼀个QShortcut(快捷键)对象作为其⼦对象。当删除按钮的时候,这个快捷键理应被删除。这是合理的。

QWidget是能够在屏幕上显⽰的⼀切组件的⽗类。

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

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

1. 对象树的构建与归属关系

  • 核心机制: 对象树并非一个独立的数据结构,而是通过每个QObject内部的QObjectList(即children())和每个子对象指向父对象的QPointer(实际上是QObject*)相互链接而形成的逻辑上的树形结构。

  • 如何加入树中: 一个QObject对象被创建到堆上时,并不会自动成为对象树的一部分。它需要通过设置父对象来加入树中。这通常有两种方式:

    • 在构造函数中指定父对象: 这是最常见的方式,例如 QPushButton *button = new QPushButton("Click", this);,其中this(通常是另一个窗口部件)作为父对象。

    • 后续调用setParent(): 可以在对象创建后,通过setParent()方法动态地改变其父对象,从而将其从一个对象树移动到另一个。

2. 内存管理的优势与简化

  • “谁创建,谁释放”的例外: 在传统的C++开发中,我们严格遵守“谁new,谁delete”的原则。Qt对象树巧妙地修改了这一规则,变为 “父对象负责析构其所有子对象”。这意味着,当你在一个父对象中创建了成百上千个子对象时,你只需要确保父对象被正确删除,所有子对象的内存都会自动回收,极大地简化了内存管理,避免了内存泄漏。

  • 任何对象树中的QObject对象delete的时候,如果这个对象有parent,则⾃动将其从parent的 children() 列表中删除;如果有孩⼦,则⾃动delete每⼀个孩⼦。

3. 析构顺序的深层含义

  • 顺序未定义但安全: Qt不保证先销毁哪个子对象,后销毁哪个。但这之所以安全,是因为Qt的保证:任何对象在其析构函数被调用时,会首先将自己从父对象的子对象列表中移除,然后再递归地销毁自己的所有子对象。这确保了:

    1. 父对象在销毁时,不会试图去访问一个已经被销毁的子对象。

    2. 一个对象绝不会被delete两次(一次由它的父对象,一次由你自己手动)。如果你手动delete了一个子对象,它会立即从父对象的列表中移除,这样当父对象后续被销毁时,就不会再尝试delete它一次。

我们看个例子

如果说我要析构QListWidget,那么我就需要先析构它的3个子对象,然后才能析构这个QListWidget.

6.3.对象树的缺点

如果QObject在栈上创建,Qt保持同样的⾏为。正常情况下,这也不会发⽣什么问题。来看下⾯的代 码⽚段:

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

但是,如果我们使⽤下⾯的代码:

情况⼜有所不同,析构顺序就有了问题。我们看到,在上⾯的代码中,作为⽗对象的window会⾸先 被析构,因为它是最后⼀个创建的对象。

在析构过程中,它会调⽤⼦对象列表中每⼀个对象的析构函 数,也就是说,quit此时就被析构了。

然后,代码继续执⾏,在window析构之后,quit也会被析 构,因为quit也是⼀个局部变量,在超出作⽤域的时候当然也需要析构。

但是,这时候已经是第⼆次 调⽤quit的析构函数了,C++不允许调⽤两次析构函数,因此,程序崩溃了。

由此我们看到,Qt的对象树机制虽然在⼀定程度上解决了内存问题,但是也引⼊了⼀些值得注意的事 情。

这些细节在今后的开发过程中很可能时不时跳出来烦扰⼀下,所以,我们最好从开始就养成良好 习惯

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

七.实验:验证对象树内存释放过程

首先我们先创建一个空项目

接下来我们点击下面这个

接下来我们会遇到下面这种图,我们可以看看下面这个图

我们这里选择继承QLabel类!!!

现在我们就多出一个.h和.cpp

头文件包含问题

但是有一个问题mylabel不认识它的父类QLabel

所以我们需要手动的给他指定一下头文件包含

修改构造函数

我们现在这个构造函数是不能被添加进对象树上的。

我们需要给构造函数添加一个Qwidget的指针。

就像下面这样子

注意:我们在Qt中,可以通过F4按钮来进行.h文件和对应.cpp文件的切换

我们将.cpp文件修改成下面这样子。

现在才能让自己的类的对象加入到Qt对象树木。

自定义析构函数

现在我们需要去.cpp文件里面添加定义,这个时候我们可以把光标指向下面

然后点击Alt+enter,就会出现下面这个

我们点击第一个即可,然后按回车,就会自动跳转到下面这里,并且生成好了我们的析构函数的定义

接下来我们就添加下面这些内容

修改widget.cpp文件

我们知道,MyLabel 类继承了 QLabel 类。

虽然 MyLabel 中只显式定义了一个构造函数和一个析构函数,但它却能够直接使用 QLabel 的 setText 函数。

这是为什么呢?

这其实正是面向对象中继承机制的核心体现。

继承的本质,是使子类自动获得父类的全部公有和保护成员(包括成员函数和数据成员),从而无需重新编写即可直接使用。

也就是说,MyLabel 对象不仅是一个 MyLabel 类型的实例,同时也是一个 QLabel 类型的实例,天然拥有 QLabel 的所有对外接口。

在当前的示例中,我们为 MyLabel 编写自定义析构函数的主要目的,并非是为了改变或删除 QLabel 的基础功能——setText 等原有方法完全保持不变。而是为了在现有功能基础上进行扩展,例如在析构时打印一行日志,以便于我们更直观地观察对象的生命周期和程序运行过程。

因此,尽管 MyLabel 的表面代码量很少,但它通过继承关系,已经完整包含了 QLabel 的功能体系。这就是为什么我们可以在 MyLabel 对象上无缝调用 setText 等父类方法的原因。

接下来我们分别点击下面这两个

我们看运行结果

接着我们点击下面这个

然后我们就能看到输出

怎么是一堆乱码啊?其实我们自己肯定知道这应该是MyLabel被销毁.

说明析构函数是执行了。

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

预期打印的是 "被销毁" 三个中文
但是实际的显示效果,出现了乱码。

乱码这个事情,咱们以后会经常涉及到~~

乱码问题出现的原因,有且只有一个(不局限于 C++)

就是编码方式不匹配!!!

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

那么我们这里的编码集是啥呢

其实就是和我们mylabel.cpp的编码集是一样的,那么mylabel.cpp的编码集怎么查看呢?我们看看下面这个

可以看到mylabel.cpp的编码集就是UTF-8。

而我们Qt Creator内置的终端是使用UTF-8来显示字符串吗?

那就不好说了。

这个终端好像不能设置字符编码~~既然出现乱码了,就说明不是使用UTF-8了。

怎么解决乱码的问题呢?

Qt 中提供了 QString 类,它能够帮助我们自动处理字符串的编码问题,大大简化了多语言和跨平台开发中的字符表示和转换。

不仅如此,Qt 还内置了专门用于日志输出的工具,同样具备自动处理编码的能力,进一步减轻了开发者的负担。

例如,我们原本可能这样输出日志:

std::cout << "MyLabel 被销毁!" << std::endl;

但在 Qt 中,更推荐使用 qDebug() 工具来完成日志打印。它内部封装了对字符编码的自动处理,开发者无需手动处理编码转换,非常方便。只需包含相应的头文件:

#include <QDebug>

需要注意的是,QDebug 是 Qt 中的一个类,但我们一般不直接使用它,而是通过 qDebug() 这个宏来输出日志。例如:

qDebug() << "MyLabel 被销毁!";

这里的 qDebug() 返回一个用于输出的对象,我们可以像使用 std::cout 一样来使用qDebug(),通过 << 操作符(输出运算符,而非移位运算符)连续输出多个内容,使用起来非常直观。

我们再次运行一下

再次点击叉

怎么样?是不是没有乱码了。

        在 Qt 开发中,建议优先选用 qDebug() 来输出调试信息。虽然使用 std::cout 在某些平台上(如 Linux,其默认编码一般为 UTF-8)可能不会出现乱码,但在 Windows 环境下,由于终端默认编码通常是 GBK,很容易出现乱码问题。而 qDebug() 能够很好地跨平台统一处理编码,避免这类问题。

        此外,qDebug() 还有一个重要优势:所有通过它输出的调试日志可以被统一管理,甚至可以在发布时一键关闭。日志信息主要是在开发调试阶段用于帮助开发者了解程序运行状态,当程序正式发布给最终用户时,我们通常不希望用户看到这些调试信息。使用 qDebug() 可以方便地通过宏定义或环境配置来控制日志的输出与否,更加灵活和高效。

验证对象树析构机制

就目前这个项目而言,我们现在还不能看出对象树的析构机制。

我们只需要再添加下面这个即可

我们再次运行我们的项目

接着我们点击

我们发现嗯?怎么是父对象的析构函数先执行?

这个是我们的一个错觉

对象树确保的是先释放⼦节点的内存,后释放⽗节点的内存. ⽽析构函数的调⽤顺序则不⼀定遵守上述要求.

因此看到⼦节点的析构执⾏顺序反⽽在⽗节点析构顺序之后。

注意:调⽤析构函数和释放内存并⾮是同⼀件事情.

八. Qt编程注意事项

8.1 Qt中的命名规范

良好的命名规范是编写可维护代码的基础,Qt框架有其特定的命名约定:

  • 类名:采用大驼峰式(UpperCamelCase),即每个单词的首字母均大写,例如 MainWindowDialogBox

  • 函数名及变量名:采用小驼峰式(lowerCamelCase),即首字母小写,后续每个单词的首字母大写,例如 openFilecurrentTextColor

需要注意的是,Qt 普遍采用驼峰命名法,这与我们之前在课堂上常用的蛇形命名法(snake_case,如 open_file)有所不同。在实际开发中,建议遵循 Qt 的命名风格以保持代码的一致性。若您参与的是已存在项目,则应优先遵循该项目的现有命名约定。

8.2 QtCreator中的快捷键

熟练使用快捷键能显著提升开发效率。Qt Creator 提供了丰富的快捷键支持,以下是一些常用操作:

  • 注释Ctrl + /,快速添加或取消单行注释。

  • 运行Ctrl + R,编译并运行当前项目。

  • 编译Ctrl + B,仅编译当前项目,而不运行。

  • 字体缩放Ctrl + 鼠标滑轮,方便地调整编辑区的字体大小。

  • 查找Ctrl + F,在当前文件中查找特定内容。

  • 整行移动Ctrl + Shift + ↑ / ↓,向上或向下移动当前行。

  • 帮助文档F1,强大的帮助工具,光标置于某个类或函数上时按下 F1,可快速查看其详细说明。

  • 自动对齐Ctrl + I,格式化当前选中的代码或整个文件,使其符合编码风格。

  • 头文件与源文件切换F4,快速在同名的 .h 和 .cpp 文件之间跳转。

  • 生成函数定义Alt + Enter,当在头文件中声明函数后,使用此快捷键可以快速在源文件中生成对应的函数定义框架。

此外,建议多探索 Qt Creator 的快捷键设置(位于 工具 -> 选项 -> 环境 -> 键盘),您可以根据个人习惯定制快捷键,从而进一步提升编程体验和工作效率。

8.3.使用帮助文档

打开帮助⽂档有三种⽅式.实际编程中使⽤哪种都可以.

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

比如说我想查询下面这个connect函数的文档,我们就先把光标移动到这里

点击F1,设计界面右边就会出现下面这个

这个就是我们的帮助文档。

如果想要关闭文档,点击这个按钮即可

方法2——QtCreator左侧边栏中直接⽤⿏标单击"帮助"按钮:

点击"帮助"之后,出现如下图⽰界⾯:

方法3——找到QtCreator的安装路径,在"bin"⽂件夹下找到assistant.exe,双击打开;

不要使⽤中⽂⽂档!

不要使⽤中⽂⽂档!

不要使⽤中⽂⽂档!

阅读英⽂⽂档是每个程序员必备的专业技能,必须要练,不能退缩.

Qt的⽂档从通俗易懂的⻆度来说,是技术类⽂档中⾮常出类拔萃的。

只要⼤家稍微有点耐⼼,基本都能读懂个⼋九不离 ⼗. 咱们后续的学习中,也会经常翻阅⽂档

九.Qt窗⼝坐标体系

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

这个和我们数学里面的坐标系还是有一点区别的

对于嵌套窗⼝,其坐标是相对于⽗窗⼝来说的。

示例

我们新建一个项目

我们运行看看

默认是在左上角的

接下来我们就来修改一下

我们添加了下面这一句

button->move(200,300);

这行代码的作用是:将 button 这个按钮移动到其父窗口(或父部件)客户区内的坐标 (200, 300) 处。这意味着,按钮左上角将位于其父部件左上角向右 200 个单位、向下 300 个单位的位置。

那么,Qt 中的坐标单位是如何定义的呢?

在 Qt 的绘图和 widget 定位系统中,默认情况下,1 个坐标单位就代表 1 个物理像素。这种设计使得开发者可以直接基于像素进行精确的界面布局和控制。

如果你想查看或设置自己电脑的屏幕分辨率(总像素尺寸),通常可以在系统设置中完成:

  • 在 Windows 上,你可以通过设置 > 系统 > 显示 > 显示分辨率来查看和调整。

我们运行看看。

我们发现按钮的位置变化了。

按照上面的理解,这个按钮的位置应该是

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐