【Qt开发】信号与槽(三)-> 自定义信号和槽

目录

[1 -> 基本语法](#1 -> 基本语法)

[2 -> 带参数的信号和槽](#2 -> 带参数的信号和槽)

[3 -> 小结](#3 -> 小结)


1 -> 基本语法

在 Qt 中,允许自定义信号的发送方以及接收方,即可以自定义信号函数和槽函数。但是对于自定义的信号函数和槽函数有一定的书写规范。

一、自定义信号函数书写规范

  1. 自定义信号函数必须写到 "signals" 下
  2. 返回值为 void,只需要声明,不需要实现
  3. 可以有参数,也可以发生重载

二、自定义槽函数书写规范

  1. 早期的 Qt 版本要求槽函数必须写到 "public slots"下,但是现在高级版本的 Qt 允许写到类的 "public" 作用域中或者全局下
  2. 返回值为 void,需要声明,也需要实现
  3. 可以有参数,也可以发生重载

三、发送信号

使用 "emit" 关键字发送信号。"emit" 是一个空的宏。"emit" 其实是可选的,没有什么含义,只是为了提醒开发人员。

示例1:

1. 在 widget.h 中声明自定义的信号和槽

2. 在 widget.cpp 中实现槽函数,并且关联信号和槽

注意:下图中的 1 和 2 的顺序不可以颠倒

因为,首先关联信号和槽,一旦检测到信号发射之后就会立马执行关联的槽函数。反之,如若先发射信号,此时还没有关联槽函数,当信号发射之后槽函数不会响应。

示例2:当老师说 "上课了",学生们就 "回到座位,开始学习"

1. 在源文件中新建两个类,一个是老师类,一个是学生类。首先选中项目名称,鼠标右键 => "add new......"

点击 "add new......" 之后,出现如下界面

选择 "choose" 出现如下界面。

注意:在 Qt 中新建类时,要选择新建类的父类。

很显然,在当前项目中还没有什么类适合做新类的父类,同时新的类也不是一个 "窗口" 或者 "控件"。这种情况一般选择 QObject 作为基类。

这样做的好处是:这个新类的对象可以搭配 Qt 的对象树机制。便于对象的正确释放。

选择 "下一步",出现如下界面

对于 "学生类" 以上述同样的方式进行添加,添加完成之后,项目目录新增文件如下

在 teacher.h 中声明信号函数

在 studio.h 中声明槽函数

在 widget.h 中实例化 "老师类对象" 和 "学生类对象"

在 studio.cpp 中实现槽函数

在 widget.cpp 中连接自定义信号和槽

运行结果如下图

示例3:老师点击 "按钮" 触发学生上课

运行结果如下图

2 -> 带参数的信号和槽

Qt 的信号和槽也支持带有参数,同时也可以支持重载。

此处要求,信号函数的参数列表要和对应连接的槽函数参数列表一致

此时信号触发,调用到槽函数时,信号函数中的实参就能够被传递到槽函数的形参中。

通过这样的机制,就可以让信号给槽传递数据了。

示例1:重载信号槽

1. 在 "widget.h" 头文件中声明重载的信号函数以及重载的槽函数

2. 在 "Widget.cpp" 文件实现重载槽函数以及连接信号和槽

注意:在定义函数指针时要指明函数指针的作用域

3. 执行结果如下图

示例2:信号槽参数列表匹配规则

1. 在 "widget.h" 头文件中声明信号和槽函数

2. 在 "widget.cpp" 文件中实现槽函数以及连接信号和槽

其实信号的参数个数可以多于槽函数的参数个数,但是槽的参数个数不能多于信号的参数个数。

但是在实际开发中最好保持参数个数也能匹配一致。

示例3:

1. 在 "widget.h" 头文件中声明信号和槽函数

2. 在 "widget.cpp"文件中实现槽函数以及连接信号和槽

3 -> 小结

一、基本语法规范

1. 自定义信号

  • 必须声明在类的 signals: 区域

  • 返回类型必须为 void,只需声明无需实现(Qt自动生成)

  • 支持参数传递和重载

  • 通过 emit 关键字触发(实际是空宏,但建议显式使用)

signals:
void mySignal(int value); // 声明

2. 自定义槽

  • 可声明在 public slots: 或普通 public: 区域

  • 需完整实现函数逻辑,返回类型为 void

  • 支持参数传递和重载

public slots:
void mySlot(int data); // 声明+实现

二、参数传递规则

  1. 核心机制

    • 信号参数自动传递给槽函数形参

    • 参数数量兼容性

      • 槽函数参数数量 信号参数数量(多余参数被忽略)

      • 禁止槽参数数量 > 信号参数数量(编译错误)

    • 参数类型必须严格匹配 (如 int 不能隐式转 QString

  2. 重载处理

    • 需用 static_cast 明确指定函数指针类型:

// 重载信号连接
connect(sender, static_cast<void(SenderClass::*)(int)>(&SenderClass::overloadedSignal),
receiver, &ReceiverClass::slotForInt);

三、实战注意事项

1. 连接顺序

  • 必须先 connectemit 信号,否则槽函数不会触发

connect(teacher, &Teacher::classBegin, student, &Student::enterClass); // 1. 连接
emit teacher->classBegin(); // 2. 触发信号

2. 对象生命周期

  • 通过 对象树机制 自动管理内存(推荐继承 QObject

  • 典型错误:槽函数访问已销毁对象 → 崩溃

  • 解决方案:

    • 使用 QPointer 弱指针

    • 显式调用 disconnect()

3. 参数设计建议

  • 优先使用 一致参数列表(避免隐式截断)

  • 跨线程传递时,参数类型需注册元类型(qRegisterMetaType


感谢各位大佬支持!!!

互三啦!!!

相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner10 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner11 天前
DicomViewer (目录调整) 2
qt
xcyxiner11 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00613 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术13 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript