【Qt】初识Qt

文章目录


认识 Qt Creator 界面


左边栏

在编辑模式下,左边竖排的两个窗口被称作"边栏"。其中,①是项目文件管理窗口,②是打开文件列表窗口。

在Qt Creator的菜单中,选择"控件" -------> "Show Left Sidebar",或者使用快捷键"Alt + 0",就能控制边栏的显示与隐藏。

边栏中的窗口数量可以增加,边栏子窗口标题栏有一排小按钮,最右边的是关闭按钮,倒数第二个是增加分栏按钮,通过它可以添加多个边栏子窗口。

边栏子窗口标题栏第一个控件是组合框,可以选择该子窗口的功能视图类型,目前可以选择 8 个视图类型:

视图类型 说明
项目 即项目文件管理视图,可以选择项目里的文件进行编辑,包括 pro 文件也可以手动编辑。
打开文档 当前已经打开的文件列表,文件名右边如果有 * 号,是该文件被修改了但尚未保存。
书签 右击代码编辑器行号位置,看到 "切换书签",可以给代码行添加书签,方便跳转到该位置。
文件系统 相当于系统里的文件资源管理器,可以查看项目文件夹在磁盘里的实际文件列表。
类视图 可以查看项目里包含的类及相应源代码文件里的成员函数、成员变量。
Git Branches 查看当前分支
大纲 编辑器所显示的当前文件的大纲列表,如名字空间、类名、成员函数、成员变量等。
Test 测试
类型层次 当前项目包含的类及其基类、派生类列表
Include Hierarchy 包含视图,显示当前项目里 .h 、.cpp 以及 Qt 类库头文件之间的包含关系。

代码编辑区

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

③:标识当前显示的文件是只读还是可写,一般都是可写的。

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

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

⑥:关闭当前显示的文档。

⑦:为当前显示的文件添加额外的C++预处理指令,一般用不到。

⑧:选择符号,可以在当前显示的文件里多个函数、类、成员变量等之间快速切换,与边栏"大纲"视图相对应。

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

⑩:代码编辑区分栏,可以增加多个编辑器窗口,显示多个打开的文档或显示较大源码文件的多个位置。

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

同一行既可以打断点也可以设置书签,二者并不冲突,实际上它们没有关联。单击行号前面的浅灰色空白区可以直接打断点,再次单击可以取消断点,另外也可以用快捷键F9设置或取消断点。代码书签一般通过右键菜单来设置,也可以用快捷键Ctrl+M设置或取消书签。

编辑区:写代码的区域。

UI设计界面

双击 widget.ui 文件,Qt Creator 会自动进入设计模式,可以对图形界面进行可视化编辑:

①:组件选择窗口。组件选择窗口分为多个组,如Layouts、Buttons、Display Widgets等,界面设计的常见组件都可以在组件选择窗口中找到。

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

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

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

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

构建区

左下角一共有四个按钮,下面分别介绍一下:

  • 第一个按钮是选择构建项目使用的 Qt 套件和构建目标程序的类型(Debug 或 Release)。对于第一个按钮,默认的是Debug,构建的是 Debug 类型的目标程序。如果需要构建 Release 版目标程序,点开左下角第一个按钮:

    这里有三种构建模式:
模式 说明
Debug 以 "-g" 模式编译,带着符号信息,优点是便于调试
Profile profile 则是在 "Debug" 和 "Release" 之间取⼀个平衡,兼顾性能和调试,可以类似的看做是性能更优又方便调试的版本。
Release "Release" 是经过优化之后,性能比 "Debug" 更上一个档次

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

如果项目配置了多个可用的Qt套件,点开左下角第一个按钮后,会看到各个套件以及构建类型。如果要切换Qt套件或构建类型,直接选中相应条目,然后点击运行按钮即可。如果构建和运行时没有出错,就会显示出构建好的目标程序界面。

  • 第二个是运行按钮,快捷键是Ctrl+R。如果还没构建项目或刚修改了代码,直接点击运行的话,Qt Creator会自动构建生成新的目标程序并运行。
  • 第三个是调试按钮,快捷键是F5。调试程序之前,Qt Creator会自动构建生成最新的目标程序,并进入调试模式。
  • 第四个是构建按钮,快捷键是Ctrl+B,只构建最新的目标程序,但不运行。

Qt Hello World 程序


使用 "按钮" 实现

纯代码方式实现


可视化操作实现

(1)双击:" widget.ui " 文件;

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

使用 "标签" 实现

存代码实现

可视化操作实现


项目文件解析


.pro 文件解析

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

clike 复制代码
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 并且为它调用 makemakefile
  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 关于应用程序的配置信息。

widget.h 文件解析


main.cpp 文件解析

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

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

widget.cpp 文件解析

widget.ui 文件解析

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

使用帮助文档


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

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

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

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

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

使用示例

  1. 新建项目,在新建的项目中使用 Qt 中的 QpushButton 控件。
  2. 打开帮助手册,在 "索引" 里面输入 QpushButton

认识对象模型(对象树)

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

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

    • 当创建一个 QObject 对象时,会看到 QObject 的构造函数接收一个 QObject 指针作为参数,这个参数就是 parent,也就是父对象指针。
    • 这相当于,在创建 QObject 对象时,可以提供一个其父对象,我们创建的这个 QObject 对象会自动添加到其父对象的 children() 列表。
    • 当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类!)
    • 这种机制在 GUI 程序设计中相当有用。例如,一个按钮有一个 QShortcut(快捷键)对象作为其
      子对象。当删除按钮的时候,这个快捷键理应被删除。这是合理的。
  • QWidget 是能够在屏幕上显示的一切组件的父类。

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

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

  • 当一个 QObject 对象在堆上创建的时候,Qt 会同时为其创建一个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。
  • 任何对象树中的 QObject 对象 delete 的时候,如果这个对象有 parent,则自动将其从 parentchildren() 列表中删除;如果有孩子,则自动 delete 每一个孩子。Qt 保证没有 QObject 会被 delete 两次,这是由析构顺序决定的。

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

作为父组件的 window 和作为子组件的 quit 都是 QObject 的子类(事实上,它们都是 QWidget 的子类,而 QWidgetQObject 的子类)。这段代码是正确的,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、执行结果分析:

  • 对象树确保的是先释放子节点的内存, 后释放父节点的内存.
  • 而析构函数的调用顺序则不一定遵守上述要求. 因此看到子节点的析构执行顺序反而在父节点析构顺序之后.

Qt 窗口坐标体系


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

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

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

运行结果如下图示:

相关推荐
charlie1145141911 小时前
IMX6ULL2025年最新部署方案2在Ubuntu24.04上编译通过Qt5.12.9且部署到IMX6ULL正点原子开发板上
linux·嵌入式硬件·qt·系统架构·嵌入式软件·移植教程
十五年专注C++开发7 小时前
面试题:请描述一下你在项目中是如何进行性能优化的?针对哪些方面进行了优化,采取了哪些具体的措施?
开发语言·数据结构·c++·qt·设计模式·性能优化
EverestVIP8 小时前
Qt 的 plugins/codecs 目录
开发语言·qt
GOTXX8 小时前
【Qt】Qt 信号与槽机制全解析
开发语言·数据库·c++·qt·多线程·用户界面
qing222222229 小时前
Qt:解决MSVC编译器下qDebug输出中文乱码的问题
qt
秋风&萧瑟9 小时前
【QT】 QT定时器的使用
qt
威桑9 小时前
Qt中 Key_Return 与 Key_Enter
开发语言·qt
神仙别闹9 小时前
基于QT(C++)+SQLServer实现(WinForm)超市管理系统
c++·qt·sqlserver
永不停转10 小时前
QT 的信号-槽机制
c++·qt