【QT】基础入门学习

news2024/9/17 7:11:52

文章目录

  • 浅析Qt应用程序的主函数
  • 使用qDebug()函数
  • 常用快捷键
  • Qt 编码风格
  • 信号槽连接模型
    • 实现方案
  • 信号和槽的工作机制
  • Qt对象树机制

浅析Qt应用程序的主函数

#include "mywindow.h"

#include <QApplication>

// 程序的入口
int main(int argc, char *argv[])
{
    // argc是命令行参数个数,argv是命令行参数
    // QApplication a(argc, argv),管理Qt程序的运行,和设置Qt应用程序,针对QWidget应用程序
    // QGuiApplication a(argc, argv),管理Qt程序的运行,和设置Qt应用程序,针对非QWidget应用程序,比如QQuick
    // QCoreApplication a(argc, argv),管理Qt程序的运行,和设置Qt应用程序,针对无界面的应用程序
    QApplication a(argc, argv);
    // MyWindow是我们自己定义的类,w是创建的对象
    MyWindow w;
    // w对象调用了show()方法
    w.show();
    // 事件循环,QEventLoop::exec(),等待鼠标或者键盘等其他的输入
    return a.exec();
}

使用qDebug()函数

如果使用qDebug()函数,要添加#include 头文件。
debug过程中比较常用的是qDebug()函数。对于Qt Creator,它是输出到应用程序输出栏。

#include "mywindow.h"
#include "ui_mywindow.h"
#include <QDebug>

MyWindow::MyWindow(QWidget *parent)
    : QMainWindow(parent)
    , i(4) // i = 4;
    , ui(new Ui::MyWindow) // ui = new Ui::MyWindow;
{
    //i = 4;
    ui->setupUi(this);
    qDebug() << "构造函数执行了!" << endl;
}

MyWindow::~MyWindow()
{
    qDebug() << "析构函数执行了!" << endl;
    delete ui;
}

常用快捷键

描述快捷键
新建文件或项目Ctrl + N
关闭当前窗口/关闭当前文件Ctrl + W
关闭所有文件Ctrl + Shift + W
关闭当前文件(windows)Ctrl + F4
运行Ctrl + R
返回上一级(返回),常用于跳转代码Alt + ←(方向左键)
进入下一级(前进),常用于跳转代码Alt + →(方向右键)
描述快捷键
自动排版对齐代码Ctrl + I
减小字体大小Ctrl + -(Ctrl + 鼠标滚轮向下)
增加字体大小Ctrl + +(Ctrl + 鼠标滚轮向上)
重置字体大小Ctrl + 0
折叠Ctrl + <
展开Ctrl + >
复制行Ctrl + Ins
复制到行下Ctrl + Alt + Down
复制到行上Ctrl + Alt + Up
在当前行上方插入新行Ctrl + Shift + Enter
在当前行下方插入新行Ctrl + Enter
查看剪切板历史Ctrl + Shift + V
剪切行Shift + Del
追加行Ctrl + J
向下移动当前行Ctrl + Shift + Down
向上移动当前行Ctrl + Shift + Up
切换函数声明/定义Ctrl + 鼠标左键/Shift + F2
编辑信号和槽F4
跳转至以}结尾的块Ctrl + }
跳转至以{开始的块Ctrl + {
打开类型层次窗口Ctrl + Shift + T

Qt 编码风格

Qt 编码风格

信号槽连接模型

在这里插入图片描述

实现方案

  1. 分别定义2个类,School类和Student类。
    在这里插入图片描述
  2. 源文件实现
    mainwindow.cpp 实现
 #include "mainwindow.h"
#include "ui_mainwindow.h"

// 主窗口类的构造函数,接受一个 QWidget* 类型的父窗口指针
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
   , ui(new Ui::MainWindow)
{
    // 调用 setupUi 函数来设置主窗口的界面布局和用户界面元素
    ui->setupUi(this);

    // 创建一个 Student 类的对象,并将其指针存储在 student_object 变量中
    student_object = new Student;
    // 创建一个 School 类的对象,并将其指针存储在 school_object 变量中
    school_object = new School;

    // 建立信号与槽的连接,当 school_object(学校对象)发出 send_message 信号时,
    // student_object(学生对象)的 comeBackToClass 槽函数将被调用
    connect(school_object, SIGNAL(send_message()), student_object, SLOT(comeBackToClass()));

    // 手动发出 school_object 的 send_message 信号,触发与之连接的槽函数
    emit school_object->send_message();
}

// 主窗口类的析构函数
MainWindow::~MainWindow()
{
    // 释放由 setupUi 函数分配的用户界面资源
    delete ui;
}

school.cpp 实现

#include "school.h"
#include <QObject>

School::School(QObject *parent) : QObject(parent)
{
    qDebug("创建一个类型:School");
}

student.cpp 实现

#include "student.h"
#include <QDebug>

Student::Student(QObject *parent) : QObject(parent)
{
    qDebug("创建一个类型:Student");
}

void Student::comeBackToClass()
{
   qDebug("学生去上课");
}
  1. 头文件实现
    以下是对这段代码添加注释后的内容:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

// 引入 Qt 的主窗口类头文件
#include <QMainWindow>

// 引入自定义的 School 类和 Student 类的头文件
#include "school.h"
#include "student.h"

// 前向声明 School 类和 Student 类,避免循环包含头文件
class School;
class Student;

// 开始 Qt 的命名空间
QT_BEGIN_NAMESPACE
// 命名空间 Ui 中定义了图形界面生成的类
namespace Ui { class MainWindow; }
// 结束 Qt 的命名空间
QT_END_NAMESPACE

// 定义 MainWindow 类,继承自 QMainWindow
class MainWindow : public QMainWindow
{
    // 声明 Q_OBJECT 宏,用于支持 Qt 的信号与槽等特性
    Q_OBJECT

public:
    // 主窗口类的构造函数,接受一个可选的父窗口指针
    MainWindow(QWidget *parent = nullptr);
    // 主窗口类的析构函数
    ~MainWindow();

private:
    // 指向由 Qt 的图形界面设计器生成的用户界面类的指针
    Ui::MainWindow *ui;
    // 指向 Student 类对象的指针
    Student *student_object;
    // 指向 School 类对象的指针
    School *school_object;
};
#endif // MAINWINDOW_H

#ifndef SCHOOL_H
#define SCHOOL_H

// 引入 Qt 的核心类头文件
#include <QObject>

// 定义 School 类,继承自 QObject
class School : public QObject
{
    // 声明 Q_OBJECT 宏,用于支持 Qt 的信号与槽等特性
    Q_OBJECT
public:
    // School 类的构造函数,接受一个可选的父对象指针
    explicit School(QObject *parent = nullptr);

    // 信号声明部分
    signals: 
        // 声明一个名为 send_message 的信号,只声明,不用定义
        void send_message();

};

#endif // SCHOOL_H
#ifndef STUDENT_H
#define STUDENT_H

// 引入 Qt 的核心类头文件
#include <QObject>

// 定义 Student 类,继承自 QObject
class Student : public QObject
{
    // 声明 Q_OBJECT 宏,用于支持 Qt 的信号与槽等特性
    Q_OBJECT
public:
    // Student 类的构造函数,接受一个可选的父对象指针
    explicit Student(QObject *parent = nullptr);

    // 信号声明部分,这里暂未声明任何信号

public slots:
    // 声明一个名为 comeBackToClass 的槽函数
    void comeBackToClass(void);
};

#endif // STUDENT_H

最终实现效果
在这里插入图片描述

信号和槽的工作机制

一、信号的发出
当某个特定的事件发生在一个对象(发送者)中时,这个对象可以发出一个信号。例如,当用户点击一个按钮时,按钮对象可以发出一个 “clicked” 信号。这个信号的发出通常是通过使用emit关键字来实现的。
信号只是一个声明,它不需要实现具体的代码逻辑。信号可以携带参数,以便在发出信号时传递一些额外的信息。
二、槽的定义和连接
槽是一个普通的成员函数,可以在任何 Qt 对象中定义。槽函数可以有不同的参数和返回值类型,具体取决于需要处理的信号。例如,一个槽函数可以用来处理按钮点击事件,执行一些特定的操作,如打开一个新窗口、更新数据等。
为了建立信号与槽的连接,可以使用connect函数。这个函数接受发送者对象、发送者发出的信号、接收者对象和接收者的槽函数作为参数。例如:connect(senderObject, SIGNAL(signalName()), receiverObject, SLOT(slotName()));。这样,当发送者发出指定的信号时,接收者的槽函数就会被调用。
三、信号与槽的调用过程
当发送者发出信号时,Qt 的元对象系统会自动查找所有与这个信号连接的槽函数,并将信号携带的参数传递给槽函数。
槽函数会在接收者对象的上下文中被调用,就像普通的成员函数一样。如果有多个接收者连接到同一个信号,那么这些接收者的槽函数会按照连接的顺序依次被调用。
信号与槽的连接是动态的,可以在运行时建立和断开。这使得程序可以根据不同的情况灵活地调整对象之间的通信关系。
总之,信号与槽机制提供了一种松耦合的通信方式,使得不同的对象可以在不了解对方内部实现的情况下进行交互。这种机制使得 Qt 程序的设计更加灵活、可维护和可扩展。

QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));
connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));//connect() 是 QObject 类的一个静态函数,而 QObject 是所有 Qt 类的基类,在实际调用时可以忽略前面的限定符,

在这里插入图片描述

Qt对象树机制

Qt 的对象树机制是一种自动管理内存的机制,它可以有效地避免内存泄漏问题,同时也方便了对象的管理和组织。

在这里插入图片描述
假设我们要收拾桌子,我们把桌子当作父对象,桌子上面的饭菜当作是子对象,我们收拾桌子之前,肯定是先收拾饭菜,然后再收拾桌子。我们把收拾桌子比作对象析构的过程:父对象析构的时候,会先析构所有的子对象

一、机制原理

在 Qt 中,当创建一个 QObject 对象时,可以将其作为另一个 QObject 对象的子对象。例如:

 // 1.通过构造函数传参
QObject *parentObject = new QObject();
QObject *childObject = new QObject(parentObject);

 // 2.通过setParent()方法
childObject ->setParent(parentObject);

这里,childObject被设置为parentObject的子对象。当父对象被销毁时,它的所有子对象也会被自动销毁。这是因为 QObject 的析构函数会遍历其所有子对象,并依次销毁它们。

二、作用和优势

  1. 内存管理

    • 通过对象树机制,无需手动跟踪和释放每个对象的内存,大大减少了内存泄漏的风险。
    • 当一个对象不再需要时,只需销毁它的父对象,就可以自动清理其所有子对象,简化了内存管理的过程。
  2. 对象组织

    • 对象树提供了一种清晰的层次结构,方便对相关对象进行组织和管理。
    • 可以通过遍历对象树来快速访问特定的对象或执行特定的操作。
  3. 信号与槽机制的便利

    • 在对象树中,信号可以自动传播到父对象和子对象,使得事件的传递更加方便和高效。
    • 可以利用对象树的结构来设计和实现复杂的交互逻辑。

三、注意事项

  1. 确保正确设置父对象:在创建对象时,务必正确设置父对象,以确保对象树的完整性。如果父对象在子对象之前被销毁,可能会导致未定义的行为。

  2. 避免循环引用:虽然对象树机制可以自动管理内存,但如果存在循环引用,可能会导致内存泄漏。例如,如果两个对象相互引用对方作为父对象或子对象,那么它们将无法被正确销毁。

  3. 手动删除对象:在某些情况下,可能需要手动删除对象。例如,如果一个对象不再需要,但它的父对象仍然存在,那么可以使用delete关键字手动删除该对象。但在手动删除对象时,需要注意避免破坏对象树的结构。

总之,Qt 的对象树机制是一种强大的内存管理和对象组织工具,可以提高开发效率,减少内存泄漏的风险。在使用 Qt 进行开发时,应充分利用对象树机制,并注意遵循其使用规则,以确保程序的稳定性和可靠性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2116296.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IDA的安装和使用

IDA Pro&#xff08;简称 IDA&#xff0c;官网地址为 https://www.hex-rays.com/products/ida/&#xff09;是一个反编译器&#xff0c;同时具备调试器的功能。IDA Pro 的功能非常强大&#xff0c;几乎所有的逆向题目都需要用到它&#xff0c;因而也被称为「逆向神器」 IDA安装…

MySQL入门到精通

一、创建数据库 CREATE DATABASE 数据库名称; 如果数据库存在&#xff0c;则会提示报错。 二、选择数据库 USE 数据库名称; 三、创建数据表 CREATE TABLE 数据表名称; 四、MySQL数据类型 MySQL支持多种类型&#xff0c;大致可以分为三类&#xff1a;数值、日期/时间和字符串…

Data Filtering Network论文浅析

time2023-09paperhttps://arxiv.org/abs/2309.17425codehttps://huggingface.co/apple/DFN5B-CLIP-ViT-H-14-378org.Apple个人博客地址http://myhz0606.com/article/dfn Motivation 训练一个好的CLIP模型依赖大规模&#xff0c;高质量的训练数据。通过爬虫&#xff0c;可以很…

S7-1200与G120变频器CU240E-2控制单元通过353报文实现PN通信的基本方法

S7-1200与G120变频器CU240E-2控制单元通过353报文实现PN通信的基本方法 西门子报文353 PKW+PZD-2/2, 6个字中前4个字是PKW用,后2个字是PZD用, 结合以上内容, 可以知道第5个字是STW1控制字,第6个字是转速给定值(PLC输出);第5个字是ZSW1是状态字,第6个字是当前转速值(P…

LeetCode:快乐数(202)

目录 题目 代码思路 双指针 代码实现 题目 202. 快乐数 - 力扣&#xff08;LeetCode&#xff09; 编写一个算法来判断一个数 n 是不是快乐数。 [ 快乐数 ] 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程…

ThinkPHP5 5.0.23-rce远程代码执行漏洞复现

漏洞描述 ThinkPHP是一款运用极广的PHP开发框架。其版本5中&#xff0c;由于框架对控制器名没有进行足够的检测&#xff0c;会导致在没有开启强制路由的情况下可执行任意方法&#xff0c;从而导致远程命令执行漏洞。 启动容器 docker-compose up -d 查看端口 docker ps 端口为…

【C++进阶】hash表的封装

文章目录 hash表哈希表的关键组成部分哈希表的优缺点优点&#xff1a;缺点&#xff1a; 常见应用场景 开放定址法实现hash表负载因子 (Load Factor)负载因子的意义负载因子的影响再散列 (Rehashing)示例 整体框架insertFinderasehash桶封装框架insertfinderase~HashTable() 总结…

从路径优化学习FastPlanner之B样条曲线平滑(二):FastPlanner中B样条曲线代码理解与解读

参考别人的博客学习 根据之前一章只是大致了解了B样条数学原理&#xff0c;实际读代码还有疑惑。 控制点是什么&#xff1f;和规划出的路径点什么关系&#xff1f; 控制点可以说我们规划出的路径点&#xff0c;即n等于轨迹点个数。也可以不是轨迹点&#xff0c;通过线性方程反解…

Einsum(Einstein summation convention)

Einsum&#xff08;Einstein summation convention&#xff09; 笔记来源&#xff1a; Permute和Reshape嫌麻烦&#xff1f;einsum来帮忙&#xff01; The Einstein summation convention is a notational shorthand used in tensor calculus, particularly in the fields of …

免费也能高质量!2024年免费录屏软件深度对比评测

我公司因为客户覆盖面广的原因经常会开远程会议&#xff0c;有时候说的内容比较广需要引用多份的数据&#xff0c;我记录起来有一定难度&#xff0c;所以一般都用录屏工具来记录会议内容。这次我们来一起探索有什么免费录屏工具可以提高我们的工作效率吧。 1.福晰录屏大师 链…

9.7(QT.Day 1)

一、自由发挥登录窗口的应用场景&#xff0c;实现一个登录窗口界面 要求&#xff1a;每行代码都有注释 【需要用到的图片或者动图&#xff0c;自己去网上找】 1.mywidget.h代码 #ifndef MYWIDGET_H #define MYWIDGET_H#include <QWidget> #include <QIcon> //图…

C++之格式化日期时间为字符串(精确到毫秒)

C11中提供了获取时间的chrono库&#xff0c;但是格式化显示太方便&#xff1b;C11还提供了格式化时间iomanip库&#xff0c;通过其put_time方法可以格式化时间到秒&#xff0c;要显示毫秒&#xff0c;就需要自己处理了。 #include <chrono> #include <string> #in…

css flex与inline-flex的区别

1、flex与inline-flex布局&#xff0c;都是弹性布局&#xff0c;盒状容器布局。 Flex 布局是什么&#xff1f;_w3cschool 2、下面一个实例来说明一下&#xff1a; 有一个要求&#xff0c;要求item增多的时候&#xff0c;不会换行&#xff0c;并且container容器也会随时item的…

【机器学习】我小学二年级妹妹都能理解的线性回归算法

什么是线性回归&#xff1f; 我小学二年级的妹妹想用压岁钱买房子&#xff0c;售楼广告上写着100万可以买100的房子&#xff0c;200万可以买200的房子&#xff0c;但是我的妹妹觉得那些房子都太小了&#xff0c;想买300的房子&#xff0c;那她应该要花多少钱呢&#xff1f; 对…

DBMS-2.2 数据库设计(2)——数据库规范化设计理论

本文章的素材与知识来自李国良老师和冠宇老师。 依赖理论 对于关系数据库中的依赖&#xff0c;分为函数依赖、多值依赖和连接依赖。 一.函数依赖 1.函数依赖 &#xff08;1&#xff09;定义&#xff1a; &#xff08;2&#xff09;理解&#xff1a; 通俗地讲&#xff0c;…

【Linux】借命令行参数的引导,探索环境变量的奥秘

目录 1.命令行参数 1.1.概念&#xff1a; 1.2.利用命令行参数打造计算器&#xff1a; 2.环境变量 2.1.环境变量是什么&#xff1f; 2.2.有什么方法可以不用带路径&#xff0c;直接就可以运行自己的程序呢&#xff1f; 法一&#xff1a; 法二&#xff1a; 2.3.通过代码…

PostgreSQL技术内幕9:PostgreSQL事务原理解析

文章目录 0.简介1.PG事务整体介绍1.1 事务类型介绍 1.2 事务模块介绍2. 代码分析 0.简介 有了上一篇数据库事务并发控制协议的介绍&#xff0c;对于数据库事务和并发控制有了基本的认识&#xff0c;本文将介绍PG事务模块&#xff0c;主要介绍PG支持的事务类型&#xff08;普通…

git为不同的项目设置不同的提交作者

方法1&#xff1a;找到项目的.git文件夹打开 打开config在下面添加自己作者信息 [user]name 作者名email 邮箱方法2&#xff1a;直接在.git文件夹设置作者名&#xff08;不使用–global参数&#xff09; git config user.name "xxxxx"如果想要修改之前提交的…

银行结算业务

1.1 银行本票 银行本票是由银行签发的,承诺自己在见票时无条件支付票款给收款人或持票人的业务。银行本票按票面划分为定额本票和不定额本票,按币种划分为人民币银行本票和外币银行本票。人民币银行本票仅在同一交换区域内使用,资金清算利用当地人民银行组织的资金清算形式…

vllm源码解析(五):LLM模型推理

八 模型推理细节探索 8.1 回顾下step的流程 def step(self) -> List[Union[RequestOutput, EmbeddingRequestOutput]]:# 多GPU并行推理时走AsyncLLMEngine分支。如果进入当前LLMEngine,性能会下降&#xff0c;这里会抛出异常。if self.parallel_config.pipeline_parallel_s…