目录

信号与槽概述

核心概念

信号的本质与呈现形式

槽的本质与特性

信号与槽的使用

连接信号与槽:connect()函数

查看内置信号与槽

通过 Qt Creator 可视化生成信号槽代码

自动生成的槽函数规则

自定义信号与槽

自定义语法规则

示例 1:基础自定义信号槽

示例 2:多对象间的自定义信号槽(老师→学生)

带参数的信号与槽

信号与槽的连接方式

一对一

一对多

多对一

信号与槽的其他关键说明

信号与槽的断开:disconnect()

Qt4 与 Qt5 信号槽的区别

使用 Lambda 表达式定义槽函数

信号与槽的优缺点

关键注意事项


信号与槽概述

核心概念

在 Qt 中,用户与控件的交互(如点击按钮、关闭窗口)被定义为事件,每个事件会触发一个信号,而控件对信号做出的响应动作则称为。信号与槽是 Qt 特有的消息传输机制,能将独立的控件关联起来(例如 “点击按钮关闭窗口”),实现交互逻辑。

信号的本质与呈现形式

本质:信号的本质是事件,由用户操作(如按钮单击、鼠标移动、键盘输入)或系统行为(如窗口刷新)触发,Qt 对应的窗口类会发出信号响应操作。

呈现形式:信号以函数形式存在(称为 “信号函数”),事件触发时,Qt 框架会自动调用对应的信号函数通知开发者。

发送者:信号由实例化的类对象发出。

槽的本质与特性

本质:槽是对信号响应的函数(称为 “槽函数”),与普通 C++ 函数的共性和差异如下:

关键说明:信号与槽的底层是函数调用,例如 “按钮点击信号(clicked())” 关联 “窗口关闭槽(close())”,本质是clicked()调用close()

信号与槽的使用

连接信号与槽:connect()函数

connect()是 QObject 类的静态成员函数,用于关联信号发送者、信号函数、接收者和槽函数,是信号槽机制的核心

函数原型

connect(
    const QObject *sender,    // 信号发送者(对象指针)
    const char *signal,       // 发送的信号(信号函数)
    const QObject *receiver,  // 信号接收者(对象指针)
    const char *method,       // 接收信号的槽函数
    Qt::ConnectionType type = Qt::AutoConnection  // 关联方式(默认自动)
);

核心参数说明

  • sender/receiver:必须是 QObject 类或其子类的对象(Qt 中大部分控件类均继承自 QObject)。
  • signal/method:需指定类作用域,例如&QPushButton::clicked(信号)、&QWidget::close(槽)。

代码示例(点击按钮关闭窗口)

查看内置信号与槽

Qt 系统自带的信号和槽需通过Qt 帮助文档查询,步骤如下:

  • 打开帮助文档,输入控件类名(如QPushButton)。
  • 在 “Contents” 中查找signals(信号)或slots(槽)关键字;若当前类无相关内容,需查看其父类(如QPushButton的父类QAbstractButton)。
  • 示例:QAbstractButton的内置信号包括clicked(bool checked = false)(点击)、pressed()(按下)、released()(释放)。

通过 Qt Creator 可视化生成信号槽代码

适合 UI 设计场景,无需手动编写connect(),步骤如下:

新建项目:创建带 UI 文件(.ui)的 Qt Widgets 项目。

设计 UI:双击.ui文件进入设计界面,拖入 “Push Button” 控件,修改文本(如 “关闭”)。

生成槽函数:右键选中按钮 → 选择 “转到槽” → 勾选clicked()信号(普通按钮常用) → 点击 “OK”。

Qt Creator 会自动在widget.h(头文件)中添加槽函数声明

widget.cpp(源文件)中添加槽函数框架

在槽函数函数定义中添加要实现的功能. 实现关闭窗⼝的效果.
对于普通按钮来说, 使⽤ clicked 信号即可. clicked(bool) 没有意义的. 具有特殊状态的按
钮(⽐如复选按钮)才会⽤到 clicked(bool) .

编写槽函数逻辑:在widget.cpp的槽函数中添加功能代码(如关闭窗口)。

自动生成的槽函数规则
  • 命名格式:on_XXX_SSS,其中XXX是控件的objectName(如pushButton),SSS是信号名(如clicked)。
  • 示例:void on_pushButton_clicked();(按钮点击触发的槽函数)。
  • 注意:建议优先使用显式connect(),避免因objectName拼写错误导致连接失效,且显式连接更易阅读。

自定义信号与槽

除了 Qt 内置的信号槽,开发者可根据需求自定义,需遵循严格的语法规范。

自定义语法规则

示例 1:基础自定义信号槽

1.头文件(widget.h)声明

2.源文件(widget.cpp)实现

示例 2:多对象间的自定义信号槽(老师→学生)

场景:老师发出 “上课了” 信号,学生响应 “回到座位学习”。

1.在源⽂件中新建两个类,⼀个是⽼师类,⼀个是学⽣类;⾸先选中项⽬名称,⿏标右键 -----> "add new..."

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

选择 "choose" 出现如下界⾯.

点击完成即可

在 teacher.h 中声明信号函数:
在 student.h 中声明槽函数:
在widget.cpp中实现功能
运行结果:

带参数的信号与槽

核心规则

  • 信号的参数个数可多于槽,但槽的参数个数不能多于信号(建议参数个数和类型完全匹配)。
  • 若参数类型不匹配,需通过函数指针明确指定重载的信号 / 槽。

示例:重载信号与槽

  • 头文件声明(widget.h):

  • 源文件实现(widget.cpp):

区分 “全局函数指针” 与 “成员函数指针”

全局函数的指针可以直接写为 返回值类型 (*指针名)(参数列表),但成员函数指针必须带 类名:: —— 这是因为成员函数隐含了一个隐藏参数 this(指向类实例的指针),导致其调用约定、内存布局与全局函数不同。因此,语法上必须用 类名:: 来明确 “这是类的成员函数的指针”,而非全局函数指针。

简言之,即使成员函数在类内定义,它依然 “属于类”,因此在声明 / 初始化指向成员函数的指针时,必须通过 类名:: 显式指定作用域,才能让编译器正确识别指针的类型和关联的类。

信号与槽的连接方式

Qt 支持一对一、一对多、多对一三种连接模式,满足不同交互场景。

一对一

模式 1:一个信号连接一个槽:单个信号触发单个槽函数(如 “按钮点击→窗口关闭”),示例见 “二、(一)”。

模式 2:一个信号连接一个信号:单个信号触发另一个信号(信号转发),示例:

一对多

一个信号触发多个槽函数,槽函数执行顺序与connect()调用顺序一致,示例:

多对一

多个信号触发同一个槽函数,示例:

信号与槽的其他关键说明

信号与槽的断开:disconnect()

用法与connect()完全一致,用于解除信号与槽的关联(如动态取消功能),示例:

Qt4 与 Qt5 信号槽的区别

Qt4 需使用SIGNAL()SLOT()宏,灵活性和类型安全性低于 Qt5,对比如下

使用 Lambda 表达式定义槽函数

Qt5 支持用 Lambda 表达式(C++11 特性)作为槽函数,无需单独声明实现槽,简化代码,尤其适合简单逻辑。

Lambda 语法格式

[capture] (params) opt -> ret {
    // 函数体
};
  • capture:捕获外部变量(常用[=]值传递所有外部变量,[&]引用传递,[this]访问类成员)。
  • params:参数列表(无参可省略)。
  • opt:可选参数(如mutable,允许修改值传递的变量副本)。
  • ret:返回值类型(可省略,编译器自动推导)。

示例 1:Lambda 作为槽(点击按钮关闭窗口)

示例 2:带参数的 Lambda

信号与槽的优缺点

关键注意事项

  • Q_OBJECT:所有使用信号槽的类必须在类声明中添加Q_OBJECT宏,否则 Qt 元编程机制无法生成信号槽代码。
  • 父对象设置:动态创建的控件(如QPushButton)需指定父对象(如this),避免内存泄漏(Qt 对象树会自动管理父对象的子对象生命周期)。
  • 关联顺序:必须先调用connect()关联信号槽,再触发信号,否则信号触发时无响应。
  • C++11 支持:使用 Lambda 表达式时,Qt5 及以上版本无需额外配置(新建项目自动添加CONFIG += C++11),Qt4 需手动在.pro文件中添加该配置。
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐