Qt信号与槽机(1)

发布时间:2026/11/6 7:44:59
Qt信号与槽机(1)

Qt 采用事件驱动的编程模型:用户对界面做的每一次操作都会触发事件,框架随之发出信号,控件再对信号做出响应。

信号与槽正是这套流程里的消息传输机制,它让相互独立的控件得以协作,也是理解 Qt 程序结构的一条主线。

这篇内容按一条主线展开:先建立对信号与槽的概念认知,再掌握连接与内置信号槽的用法,编写自定义信号槽并处理带参与重载的情况,梳理常见的几种连接关系,最后补充断开、Qt4 写法与 Lambda 槽函数等进阶用法。

一、基础认知

1.1 事件、信号与槽

在 Qt 中,用户和控件的每次交互过程都是一个事件。

点击按钮是事件,关闭窗口也是事件。每个事件都会产生一个信号,比如按钮被点击时发出“按钮被点击”的信号,窗口关闭时发出“窗口被关闭”的信号。

信号与槽能把相互独立的控件关联起来。按钮和窗口原本互不影响,点击按钮并不会对窗口造成影响;借助信号与槽机制,就能实现“点击按钮使窗口关闭”的效果。

1.2本质

信号的本质是事件。

用户对窗口或控件执行了某些操作,触发特定事件后,Qt 对应的窗口类就会发出某个信号来回应这次操作。比如按钮的单击、双击,窗口的刷新,鼠标的移动、按下、释放,键盘的输入,都属于能被框架捕捉的事件。对哪个窗口进行操作,哪个窗口就能捕捉到这些事件。

槽的本质是对信号响应的函数。

槽函数和普通 C++ 函数没有本质差别,可以定义在类的各个访问区域,可以带任意参数,可以被重载,也可以被直接调用,只是不能有默认参数。

实现层面有两点值得留意。

(1)信号和槽机制底层是函数间的相互调用。每个信号都能用函数表示,每个槽也能用函数表示。

(2)信号函数和槽函数通常位于某个类中,与普通成员函数相比,特别之处在于:信号函数用 signals 关键字修饰,槽函数用 public slots、protected slots 或 private slots 修饰,signals 和 slots 是 Qt 在 C++ 基础上扩展的关键字。

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

对比项

信号函数

槽函数

关键字

signals

public slots / protected slots / private slots

声明与定义

只需要声明

声明与实现都需要

函数体

由 Qt 自动生成

由开发者编写

触发方式

事件触发、emit 发射

关联信号后自动执行,也可直接调用

默认参数

—

不能有默认参数

二、基本使用

2.1 连接信号和槽

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

QObject 是 Qt 内置的父类,Qt 提供的很多类都直接或间接继承自它,这一点和 Java 的继承体系比较相似。

connect() 的函数原型:

参数

含义

sender

信号的发送者

signal

发送的信号

receiver

信号的接收者

method

接收信号的槽函数

type

关联方式,默认 Qt::AutoConnection

拿“在窗口中设置一个按钮,点击按钮关闭窗口”来示范:

#include "widget.h" #include <QPushButton> Widget::Widget(QWidget *parent) : QWidget(parent) { QPushButton *btn = new QPushButton("关闭窗口", this); // 创建按钮 resize(800, 600); // 调整窗口大小 // 关联信号和槽:点击“按钮”关闭“窗口” connect(btn, &QPushButton::clicked, this, &QWidget::close); } Widget::~Widget() { }

2.2 查看内置信号和槽

系统自带的信号和槽,通常通过 Qt 的帮助系统来查询。以查询按钮的信号为例,输入 QPushButton 后按下面的顺序找:

  1. 在 Contents 中寻找关键字 signals

  2. 没有找到时,继续去父类 QAbstractButton 中查找 signals

  3. 在列出的信号中找到 clicked()

QAbstractButton 里的信号主要有这几个:

信号

触发时机

void clicked(bool checked = false)

按钮被点击时发出

void pressed()

按钮被按下时发出

void released()

按钮被释放时发出

void toggled(bool checked)

按钮状态切换时发出

槽函数的查找方式与信号一致,只是关键字换成 slot。

2.3 借助 Qt Creator 生成信号槽代码

Qt Creator 可以快速帮助生成信号槽相关的代码。目标还是实现“点击按钮关闭窗口”,操作分成几个环节:

(1)新建项目并保留 UI 设计文件

新建项目时注意勾选生成 UI 设计文件,完成后项目里会多出一个 widget.ui 文件。

(2)进入 UI 设计界面

双击 widget.ui 文件进入设计模式,左侧是控件工具箱,中间是设计画布,右侧是属性面板与对象列表。

(3)拖入按钮并修改属性

从控件工具箱的 Buttons 分组中把 Push Button 拖到画布上,再修改按钮的名称(objectName)、文本及字体大小等属性。

(4)可视化生成槽函数

先选中按钮组件,点击鼠标右键,在弹出的菜单中单击“转到槽…”。

对按钮来说,点击时发送的信号是 clicked(),因此在弹出的对话框中选择 clicked()。

普通按钮使用 clicked 信号即可,clicked(bool) 对普通按钮没有实际意义,具有特殊状态的按钮(比如复选按钮)才会用到 clicked(bool)。

(5)自动生成槽函数原型框架

选择信号后,Qt Creator 会自动生成槽函数的原型框架:在 widget.h 头文件中添加槽函数声明,在 widget.cpp 中生成槽函数定义。

(6)补充槽函数的功能代码

在自动生成的槽函数定义中,添加要实现的功能,这里写入 this->close(),实现关闭窗口的效果。

2.4 自动生成槽函数的命名规则

自动生成的槽函数遵循 on_XXX_SSS 的命名规则:

  • 以 on 开头,中间用下划线连接起来

  • XXX 表示对象名

  • SSS 表示对应的信号

例如 on_pushButton_clicked(),pushButton 是对象名,clicked 是对应的信号。按照这种命名风格定义的槽函数,会被 Qt 自动与对应的信号连接。

日常写代码时,除非是 IDE 自动生成,否则建议显式使用 connect,而不是依赖命名规则。

显式 connect 一方面能更清晰直观地描述信号和槽的连接关系,另一方面也能避免信号或槽名字拼写错误导致连接失效。

至于配置大于约定还是约定大于配置,业界尚有争议,这里更推荐优先考虑显式 connect。