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

Qt:项目文件解析

目录

QWidget基础项目文件解析

.pro文件解析

widget.h文件解析

widget.cpp文件解析

widget.ui文件解析

main.cpp文件解析

认识对象模型

窗口坐标系


QWidget基础项目文件解析

.pro文件解析

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

双击进入该文件,该文件的核心内容如下: 

QT       += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS
TARGET = QtTest
TEMPLATE = appSOURCES += \main.cpp \widget.cppHEADERS += \widget.hFORMS += \widget.ui
  • 注释:从"#"开始,直到该行结束
  • QT += core gui:Qt包含的模块

  • greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

这条语句的含义是,若QT_MAJOR_VERSION大于4,即当前使用的Qt5及更高版本,需要增加widgets模块。若项目仅需支持Qt5,也可以直接添加"QT += widgets"⼀句。不过为了保持代码兼容,最好还是按照Qt Creator生成的语句编写。

  • CONFIG += c++11

CONFIG用来告诉qmake关于应用程序的配置信息,上述语句说明使用c++11的特性

  • DEFINES += QT_DEPRECATED_WARNINGS

定义编译选项。QT_DEPRECATED_WARNINGS表示当Qt的某些功能被标记为过时的,那么编译器会发出警告。

  • TARGET = QtTest:指定生成的应用程序名
  • TEMPLATE = app:告诉qmake为这个应用程序生成哪种makefile
app建立一个应用程序的makefile,默认值,若模板没有被指定,这个将会被使用
lib建立一个库的makefile
vcapp建立一个应用程序的VisualStudio项目文件
vclib建立一个库的VisualStudio项目文件
subdirs这是一个特殊的模板。它可以创建一个能够进入特定目录的makefile并且为它调用make的makefile
  • 工程中包含的源文件:SOURCES += main.cpp/widget.cpp
  • 工程中包含的头文件:HEADERS += widget.h
  • 工程中包含的资源文件:RESOURCES += painter.qrc
  • 工程中包含的"ui"设计文件:FORMS += widget.ui

widget.h文件解析

在Qt中,若要使用信号与槽(signal和slot)的机制就必须加入Q_OBJECT宏。

Ui::Widget *ui;这个指针是用前面声明的namespace Ui中的Widget类定义的(不是同一个Widget),所以指针ui指向可视化设计的界面,后面要访问界面上的组件,都需要通过这个指针ui去访问。

Ui:Widget继承自Ui_Widget类,Ui_Widget类位于ui_widget.h文件中,ui_widget.h文件是对widget.ui文件编译后自动生成的。


widget.cpp文件解析

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


widget.ui文件解析

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


main.cpp文件解析

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

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

认识对象模型

在Qt中创建很多对象的时候会提供一个parent对象指针,这个parent到底是干什么的呢?

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

  • 当创建一个QObject对象时,会看到QObject的构造函数接收⼀个QObject指针作为参数,这个参数就是parent,即父对象指针
  • 在创建QObject对象时,可以提供⼀个其父对象,创建的这个QObject对象会自动添加到其父对象的children()列表
  • 当父对象析构的时候,这个列表中的所有对象也会被析构(这里的父对象并不是继承意义上的父类)

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

QWidget是能够在屏幕上显示的一切组件的父类

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

对象树机制一定程度上解决了内存问题

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

若QObject在栈上创建,Qt保持同样的行为。正常情况下也不会发生什么问题

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

上述代码的析构顺序就有了问题。在上面的代码中,作为父对象的window会先被析构,因为它是最后一个创建的对象。在析构过程中,它会调用子对象列表中每一个对象的析构函数,即quit此时就被析构了。然后代码继续执行,在window析构之后,quit也会被析构,因为quit也是⼀个局部变量,在超出作用域的时候当然也需要析构。但是,这时候已经是第⼆次调用quit的析构函数了,C++不允许调用两次析构函数,因此,程序崩溃了。

自定义MyPushButton类观察释放过程

mypushbutton.h:

#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H#include <QPushButton>
#include <QDebug>class MyPushButton : public QPushButton
{Q_OBJECT
public:explicit MyPushButton(QWidget *parent = nullptr);~MyPushButton();//添加MyPushButton类的析构函数signals:};#endif // MYPUSHBUTTON_H

mypushbutton.cpp:

#include "mypushbutton.h"MyPushButton::MyPushButton(QWidget *parent) : QPushButton(parent)
{qDebug() << "我的按钮的构造函数被调用";
}MyPushButton::~MyPushButton()
{qDebug() << "我的按钮的析构函数被调用";
}

widget.cpp:

#include "widget.h"
#include "ui_widget.h"
#include "mypushbutton.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);MyPushButton* button = new MyPushButton(this);//传入this,将其设置到对象树中,当窗口关闭时就会自动调用其析构函数button->setText("我的按钮");
}Widget::~Widget()
{qDebug() << "Widget的析构函数被调用";delete ui;
}

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

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

总结:

Qt的对象树机制虽然在⼀定程度上解决了内存问题,但是也引入了⼀些值得注意的事情。这些细节在今后的开发过程中很可能时不时跳出来烦扰一下,所以最好从开始就养成良好习惯

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


窗口坐标系

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

对于嵌套窗口,其坐标是相对于父窗口而言的

可以使用代码设置控件在坐标系中的位置

#include "widget.h"
#include "ui_widget.h"
#include "mypushbutton.h"
#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* btn1 = new QPushButton("按钮1", this);btn1->move(200, 300);QPushButton* btn2 = new QPushButton("按钮2", this);qDebug() << "按钮1的坐标为:[" << btn1->x() << "," << btn1->y() << "]";qDebug() << "按钮2的坐标为:[" << btn2->x() << "," << btn2->y() << "]";
}Widget::~Widget()
{delete ui;
}

200与300都代表着像素点

相关文章:

Qt:项目文件解析

目录 QWidget基础项目文件解析 .pro文件解析 widget.h文件解析 widget.cpp文件解析 widget.ui文件解析 main.cpp文件解析 认识对象模型 窗口坐标系 QWidget基础项目文件解析 .pro文件解析 工程新建好之后&#xff0c;在工程目录列表中有⼀个后缀为 ".pro" …...

【学术投稿】第五届计算机网络安全与软件工程(CNSSE 2025)

重要信息 官网&#xff1a;www.cnsse.org 时间&#xff1a;2025年2月21-23日 地点&#xff1a;中国-青岛 简介 第五届计算机网络安全与软件工程&#xff08;CNSSE 2025&#xff09;将于2025年2月21-23日在中国-青岛举行。CNSSE 2025专注于计算机网络安全、软件工程、信号处…...

Java 大视界 -- Java 大数据在智能供应链中的应用与优化(76)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

WEB攻防-文件下载文件读取文件删除目录遍历目录穿越

目录 一、文件下载漏洞 1.1 文件下载案例&#xff08;黑盒角度&#xff09; 1.2 文件读取案例&#xff08;黑盒角度&#xff09; 二、文件删除 三、目录遍历与目录穿越 四、审计分析-文件下载漏洞-XHCMS 五、审计分析-文件读取漏洞-MetInfo-函数搜索 六、审计分析-…...

部署open webui 调用ollama启动的deepseek

以下是 部署Open WebUI并调用Ollama的deepseek-70b模型 的详细步骤&#xff0c;重点讲解部署和配置过程&#xff1a; 一、部署 Open WebUI 1. 安装Docker&#xff08;如已安装可跳过&#xff09; # 自动安装Docker curl -fsSL https://get.docker.com | sh # 启动Docker服务 …...

理解推理型大语言模型

构建和改进推理模型的方法与策略 本文描述了构建推理模型的四种主要方法&#xff0c;以及我们如何增强大型语言模型&#xff08;LLM&#xff09;的推理能力。我希望这能为你提供有价值的见解&#xff0c;并帮助你了解这一领域快速发展的文献和热潮。 在2024年&#xff0c;LLM…...

告别人工检测!casaim自动化三维激光扫描

在工业制造和工程领域&#xff0c;传统的质量检测方法主要依赖人工操作&#xff0c;不仅效率低下&#xff0c;而且容易受到人为因素的影响&#xff0c;导致检测结果的不一致性和重复性差。 传统人工检测的局限性&#xff1a; 传统的人工检测方法&#xff0c;如使用卡尺、千分…...

使用云效解决docker官方镜像拉取不到的问题

目录 前言原文地址测试jenkins构建结果:后续使用说明 前言 最近经常出现docker镜像进行拉取不了&#xff0c;流水线挂掉的问题&#xff0c;看到一个解决方案: 《借助阿里个人版镜像仓库云效实现全免费同步docker官方镜像到国内》 原文地址 https://developer.aliyun.com/artic…...

Linux TCP 编程详解与实例

一、引言 在网络编程的领域中&#xff0c;TCP&#xff08;Transmission Control Protocol&#xff09;协议因其可靠的数据传输特性而被广泛应用。在 Linux 环境下&#xff0c;使用 C 或 C 进行 TCP 编程可以实现各种强大的网络应用。本文将深入探讨 Linux TCP 编程的各个方面&…...

认识O(NlogN)的排序

归并排序 归并排序&#xff08;任何一个递归&#xff09;如果不懂可以画一个树状结构去帮助自己去理解。 核心排序方法为Merger public class 归并排序 {public static void main(String[] args) {int[] arr1 {3, 1, 2, 2, 5, 6};int[] arr2 Arrays.copyOf(arr1, arr1.len…...

[手机Linux] onepluse6T 系统重新分区

一&#xff0c;刷入TWRP 1. 电脑下载 Fastboot 工具&#xff08;解压备用&#xff09;和对应机型 TWRP&#xff08;.img 后缀文件&#xff0c;将其放入前面解压的文件夹里&#xff09; 或者直接这里下载:TWRP 2. 将手机关机&#xff0c;长按音量上和下键 开机键 进入 fastbo…...

对ReentrantLock的公平性进行测试

ReentrantLock公平性实现原理 在ReentrantLock类内部定义了一个内部类Sync以及两个实现NonfairSync和FairSync&#xff0c;它们内部定义了锁获取和释放的逻辑&#xff0c;下面我列出了两种同步类的代码&#xff0c;通过观察两个代码的差异就可以看到公平性是如何实现的。 Nonf…...

LabVIEW之TDMS文件

在很多场合&#xff0c;早期的LabVIEW版本不得不借助常规的数据库来做一些数据管理工作&#xff0c;但常规数据库对于中高速数据采集显然是不合适的&#xff0c;因为高速数据采集的数据量非常大&#xff0c;用一般的数据库无法满足存储数据的要求。 直到TDM(Technical Data Ma…...

DeepSeek 实现原理探析

DeepSeek 实现原理探析 引言 DeepSeek 是一种基于深度学习的智能搜索技术&#xff0c;它通过结合自然语言处理&#xff08;NLP&#xff09;、信息检索&#xff08;IR&#xff09;和机器学习&#xff08;ML&#xff09;等多领域的技术&#xff0c;旨在提供更加精准、智能的搜索…...

2021 年 9 月青少年软编等考 C 语言五级真题解析

目录 T1. 问题求解思路分析T2. 抓牛思路分析T3. 交易市场思路分析T4. 泳池思路分析T1. 问题求解 给定一个正整数 N N N,求最小的 M M M 满足比 N N N 大且 M M M 与 N N N 的二进制表示中有相同数目的 1 1 1。 举个例子,假如给定 N N N 为 78 78 78,二进制表示为 …...

洛谷网站: P3029 [USACO11NOV] Cow Lineup S 题解

题目传送门&#xff1a; P3029 [USACO11NOV] Cow Lineup S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 前言&#xff1a; 这道题的核心问题是在一条直线上分布着不同品种的牛&#xff0c;要找出一个连续区间&#xff0c;使得这个区间内包含所有不同品种的牛&#xff0c;…...

编程领域的IO模型(BIO,NIO,AIO)

目前对于市面上绝大多数的应用来说&#xff0c;不能实现的业务功能太少了。更多的是对底层细节&#xff0c;性能优化的追求。其中IO就是性能优化中很重要的一环。Redis快&#xff0c;mysql缓冲区存在的意义。都跟IO有着密切关系。IO其实我们都在用&#xff0c;输入输出流这块。…...

DeepSeek和ChatGPT的对比

最近DeepSeek大放异彩&#xff0c;两者之间有什么差异呢&#xff1f;根据了解到的信息&#xff0c;简单做了一个对比。 DeepSeek 和 ChatGPT 是两种不同的自然语言处理&#xff08;NLP&#xff09;模型架构&#xff0c;尽管它们都基于 Transformer 架构&#xff0c;但在设计目标…...

Pyqt 的QTableWidget组件

QTableWidget 是 PyQt6 中的一个表格控件&#xff0c;用于显示和编辑二维表格数据。它继承自 QTableView&#xff0c;提供了更简单的方式来处理表格数据&#xff0c;适合用于需要展示结构化数据的场景。 1. 常用方法 1.1 构造函数 QTableWidget(parent: QWidget None)&#x…...

4. 【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--什么是微服务--微服务设计原则与最佳实践

相比传统的单体应用&#xff0c;微服务架构通过将大型系统拆分成多个独立的小服务&#xff0c;不仅提升了系统的灵活性和扩展性&#xff0c;也带来了许多设计和运维上的挑战。如何在设计和实现微服务的过程中遵循一系列原则和最佳实践&#xff0c;从而构建一个稳定、高效、易维…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...