【QT 一 | 信号和槽】

news/2025/2/27 10:06:03

Qt5基本模块

在这里插入图片描述

Qt Creator 中的快捷键

• 注释:ctrl + /
• 运⾏:ctrl + R
• 编译:ctrl + B
• 字体缩放:ctrl + 鼠标滑轮
• 查找:ctrl + F
• 整行移动:ctrl + shift + ⬆/⬇
• 帮助⽂档:F1
• 自动对齐:ctrl + i;
• 同名之间的 .h 和 .cpp 的切换:F4
• 生成函数声明的对应定义: alt + enter

认识对象模型(对象树)

在 Qt 中,对象树是一种非常重要的概念,用于管理和组织对象之间的关系。以下是对 Qt 对象树的详细理解介绍:

1. 对象树的基本概念

  • 定义:Qt 的对象树是一种层次化的对象管理机制,基于 QObject 类实现。每个 QObject 对象可以有一个父对象(parent),并且可以拥有多个子对象(children)。
  • 父子关系:当创建一个 QObject 对象时,可以通过构造函数指定一个父对象。如果指定了父对象,那么这个新创建的对象会自动成为父对象的子对象,并被添加到父对象的 children() 列表中。

2. 对象树的作用

  • 生命周期管理:父对象负责管理其子对象的生命周期。当父对象被销毁时,其所有子对象也会被自动销毁。这种机制避免了内存泄漏,同时也简化了对象的管理。

  • 事件传播:在 GUI 程序中,事件(如鼠标点击、键盘输入等)会从父对象向下传播到子对象。这种机制使得事件处理更加高效和灵活。

  • 组件化管理:对象树使得 GUI 组件的组织更加清晰。例如,一个窗口(QWidget)可以包含多个按钮、文本框等子组件。当窗口被销毁时,所有子组件也会被自动销毁。

3. 对象树的实现机制

  • 构造函数中的父对象参数QObject 的构造函数接受一个 QObject* 类型的参数,表示父对象。例如:
    QObject* parent = new QObject();
    QObject* child = new QObject(parent);
    
    在这个例子中,child 的父对象是 parentchild 会被自动添加到 parentchildren() 列表中。
  • children() 方法:每个 QObject 对象都有一个 children() 方法,返回一个包含所有子对象的列表。
  • 自动销毁机制:当父对象被销毁时,Qt 会自动调用子对象的析构函数,销毁所有子对象。

4. 对象树的使用场景

  • GUI 组件管理:在 Qt 的 GUI 程序中,QWidget 是所有可视组件的基类,它继承自 QObject。例如:
    QWidget* window = new QWidget();
    QPushButton* button = new QPushButton(window);
    
    在这个例子中,buttonwindow 的子组件。当 window 被销毁时,button 也会被自动销毁。
  • 资源管理:对象树机制不仅适用于 GUI 组件,还可以用于管理其他资源,如文件句柄、网络连接等。

5. 注意事项

  • 避免循环引用:在使用对象树时,要避免创建循环引用(即对象 A 是对象 B 的父对象,同时对象 B 也是对象 A 的父对象)。这会导致对象无法正确销毁,从而引发内存泄漏。
  • 手动管理子对象:虽然对象树会自动管理子对象的生命周期,但也可以手动删除子对象。例如:
    QObject* child = new QObject(parent);
    delete child;  // 手动删除子对象
    
    在这种情况下,子对象会从父对象的 children() 列表中自动移除。

Qt 的对象树是一种强大的机制,用于管理和组织对象之间的关系。它不仅简化了内存管理,还使得 GUI 组件的组织更加清晰。通过合理使用对象树,可以提高代码的可维护性和可扩展性。
在 Qt 中,尽量在构造的时候就指定parent对象,并且⼤胆在堆上创建。
在这里插入图片描述## 信号与槽
如果要使用信号与槽(signal 和 slot)的机制就必须加入Q_OBJECT宏;这个宏不仅用于支持信号与槽机制,还允许 Qt 的元对象系统(Meta-Object System)自动生成一些辅助代码。

信号的本质就是事件。

  • 如:按钮单击、双击 ,窗⼝刷新等。
  • 信号的呈现形式就是函数
  • 信号函数只需要声明,不需要定义(实现)。
  • 信号函数声明用 signals 关键字修饰

槽(Slot)就是对信号响应的函数。

  • 槽是普通的成员函数,用于处理信号。槽函数可以手动实现,也可以通过 Qt 的机制自动生成。
  • 可以定义在类的任何位置( public、protected 或 private)。
  • 可以具有任何参数,可以被重载,也可以被直接调
    用(但是不能有默认参数
  • 槽函数需要定义(实现)。
  • 槽函数可以与⼀个信号关联,当信号被发射时,关联的槽函数被自动执行。
  • 槽函数用 public slots、protected lots 或者 private slots 修饰。

signals 和 slots 是 Qt 在 C++ 的基础上扩展的关键字

connect函数

在 Qt 中,QObject 类提供了⼀个静态成员函数connect(),该函数专门来关联指定的信号函数和槽函数。
connect函数原型

connect (const QObject *sender,
const char * signal ,
const QObject * receiver ,
const char * method ,
Qt::ConnectionType type = Qt::AutoConnection )

参数说明:
• sender:信号的发送者;
• signal:发送的信号(信号函数);
• receiver:信号的接收者;
• method:接收信号的槽函数;
• type:用于指定关联方式,默认的关方式为 Qt::AutoConnection,通常不需要手动设定。

自动生成槽函数的机制

  • 步骤
    1. 在 Qt Creator 中,添加一个信号( mySignal(int value)
    2. 右键点击信号或信号声明。
    3. 选择 “转到槽”(Go to Slot)或 “转到信号”(Go to Signal)。
    4. Qt Creator 会自动生成一个槽函数的声明和定义,并将其添加到类中。

例如,对于信号 mySignal(int value),Qt Creator 会生成如下代码:

// 在头文件中自动生成槽函数声明
public slots:
    void on_mySignal(int value);

// 在实现文件中自动生成槽函数定义
void MyObject::on_mySignal(int value)
{
    // 在这里实现槽函数的逻辑
}
  • 自动生成的槽函数
    • 当你在类中声明信号时,Qt 的元对象系统会自动为这些信号生成默认的槽函数。这些槽函数通常以 on_<SignalName> 的形式命名。
    • 按照这种命名风格格定义的槽函数,会被 Qt ⾃动的和对应的信号进行连接。
      日常写代码,最好还是不要依赖命名规则,而是显式
      使用 connect 更好。1. connect 可以更清晰直观的描述信号和槽的连接关系。2. 防止信号或者槽的名字拼写错误导致连接失效.
  • 使用方法
    • 在类的声明中,添加信号声明。
    • 在类的实现中,实现自动生成的槽函数。
    • 使用 QObject::connect() 将信号连接到自动生成的槽函数。
通过 Qt 的 Q_INVOKABLE

Q_INVOKABLE 宏可以将普通成员函数标记为可调用的槽函数。虽然这不是严格意义上的“自动生成”,但它允许开发者将任意函数作为槽函数使用。

  • 使用方法
    • 在类的声明中,使用 Q_INVOKABLE 宏标记成员函数。
    • 这些函数可以直接作为槽函数使用。

例如:

class MyObject : public QObject
{
    Q_OBJECT
public:
    MyObject(QObject* parent = nullptr);

    Q_INVOKABLE void mySlotFunction(int value);  // 使用 Q_INVOKABLE 标记

signals:
    void mySignal(int value);
};

void MyObject::mySlotFunction(int value)
{
    qDebug() << "Slot function called with value:" << value;
}

// 连接信号和槽
connect(this, &MyObject::mySignal, this, &MyObject::mySlotFunction);

自定义信号函数和槽函数

  1. ⾃定义信号函数书写规范
    (1)⾃定义信号函数必须写到 “signals” 下;
    (2)返回值为 void,只需要声明,不需要实现;
    (3)可以有参数,也可以发生重载
  2. ⾃定义槽函数书写规范
    (1)早期的 Qt 版本要求槽函数必须写到 “public slots” 下,但是现在⾼级版本的 Qt 允许写到类的 “public” 作用域中或者全局下;
    (2)返回值为 void,需要声明,也需要实现;
    (3)可以有参数,可以发生重载;
    3、发送信号
    使用 “emit” 关键字发送信号。“emit” 是⼀个空的宏。"emit"其实是可选的,没有什么含义,只
    是为了提醒开发⼈员。

关联函数一定要在发射信号之前
原因是,⾸先关联信号和槽,⼀旦检测到信号发射之后就会立即执行关联的槽函数。反之,若先发射信号,此时还没有关联槽函数,当信号发射之后槽函数不会响应。

信号与槽的断开

在这里插入图片描述
当"connect"函数第三个参数为"this" 时,第四个参数使⽤ Lambda表达式时,可以省略掉 “this”


http://www.niftyadmin.cn/n/5869924.html

相关文章

软件工程应试复习(考试折磨版)

针对学校软件工程考试&#xff0c;参考教材《软件工程导论&#xff08;第6版&#xff09;》1-8章 学习的艺术&#xff1a;不断地尝试&#xff0c;我一定会找到高效用的方法&#xff0c;让学习变成一门艺术&#xff0c;从应试备考中解救出我的时间同胞们。 好嘞&#xff01;既然…

数据探索实验

数据探索 1.分析1996~2015年人口总数趋势 ### 1&#xff09;训练要点 &#xff08;1&#xff09;掌握NumPy读取数据的方法 &#xff08;2&#xff09;掌握pyplot基础语法 &#xff08;3&#xff09;掌握散点图绘制方法 ### 2&#xff09;需求说明 人口数据总共有6个特征…

《机器学习数学基础》补充资料:从几何角度理解矩阵

《机器学习数学基础》第 2 章&#xff0c;专门讲解矩阵&#xff0c;因为它在线性代数中占据重要地位&#xff0c;也就是在机器学习中&#xff0c;占据重要定位了。为了更好地理解矩阵&#xff0c;本文从几何角度&#xff0c;更直观地对矩阵的某些性质和特征给予阐述。 注&…

Android OpenGLES2.0开发(十一):渲染YUV

人生如逆旅&#xff0c;我亦是行人 Android OpenGLES开发&#xff1a;EGL环境搭建Android OpenGLES2.0开发&#xff08;一&#xff09;&#xff1a;艰难的开始Android OpenGLES2.0开发&#xff08;二&#xff09;&#xff1a;环境搭建Android OpenGLES2.0开发&#xff08;三&am…

nodejs用ws模块反向代理socks5数据,即用ws写服务端和客户端及加密

首先思路是客户端发送socks5请求数据——>服务端解密并解析socks5数据是否为真&#xff0c;解析出Host和port,并用net.socket访问目标网站&#xff0c;目标网站返回数据&#xff0c;服务端再用ws发送返回数据给客户端 //解析socks5数据和返回socks5格式响应 //在读下面代码…

Spring Boot @Component注解介绍

Component 是 Spring 中的一个核心注解&#xff0c;用于声明一个类为 Spring 管理的组件&#xff08;Bean&#xff09;。它是一个通用的注解&#xff0c;可以用于任何层次的类&#xff08;如服务层、控制器层、持久层等&#xff09;。通过 Component 注解&#xff0c;Spring 会…

C#开发的Base64编码及解码完整源码及注意事项

在软件开发时&#xff0c;经常用Base64编码和解码功能。本文介绍一个简单易用的Base64 编码和解码工具&#xff0c;顾名思义&#xff0c;就是简单快捷地进行 Base64 代码的解码或编码操作。您的数据可以轻松地编码为 Base64 编码&#xff0c;也可以解码为可读的格式。传输数据时…

《论微服务架构及其应用》审题技巧 - 系统架构设计师

论微服务架构及其应用写作框架 一、考点概述 本论题“论微服务架构及其应用”主要考查考生对微服务架构的理解、应用经验以及软件设计实现能力。微服务架构作为当前软件开发领域的重要趋势&#xff0c;其核心思想是将单一应用程序拆分成一组小型、自治的服务&#xff0c;每个…