Qt信号和槽机制详解

article/2025/10/1 15:46:13

Qt信号和槽机制详解

信号和槽是 Qt 特有的消息传输机制,它能将相互独立的控件关联起来。

举个简单的例子,按钮和窗口本是两个独立的控件,点击按钮并不会对窗口造成任何影响。通过信号和槽机制,我们可以将按钮和窗口关联起来,实现“点击按钮会使窗口关闭”的效果。

信号和槽

在 Qt 中,用户和控件的每次交互过程称为一个事件,比如“用户点击按钮”是一个事件,“用户关闭窗口”也是一个事件。每个事件都会发出一个信号,例如用户点击按钮会发出“按钮被点击”的信号,用户关闭窗口会发出“窗口被关闭”的信号。

Qt 中的所有控件都具有接收信号的能力,一个控件还可以接收多个不同的信号。对于接收到的每个信号,控件都会做出相应的响应动作。例如,按钮所在的窗口接收到“按钮被点击”的信号后,会做出“关闭自己”的响应动作;再比如输入框自己接收到“输入框被点击”的信号后,会做出“显示闪烁的光标,等待用户输入数据”的响应动作。在 Qt 中,对信号做出的响应动作就称为槽。

在这里插入图片描述

图 1 信号和槽

信号和槽机制底层是通过函数间的相互调用实现的。每个信号都可以用函数来表示,称为信号函数;每个槽也可以用函数表示,称为槽函数。例如,“按钮被按下”这个信号可以用 clicked() 函数表示,“窗口关闭”这个槽可以用 close() 函数表示,信号和槽机制实现“点击按钮会关闭窗口”的功能,其实就是 clicked() 函数调用 close() 函数的效果。

信号函数和槽函数通常位于某个类中,和普通的成员函数相比,它们的特别之处在于:

信号函数用 signals 关键字修饰,槽函数用 public slots、protected slots 或者 private slots 修饰。signals 和 slots 是 Qt 在 C++ 的基础上扩展的关键字,专门用来指明信号函数和槽函数;

信号函数只需要声明,不需要定义(实现),而槽函数需要定义(实现)。

为了提高程序员的开发效率,Qt 的各个控件类都提供了一些常用的信号函数和槽函数。例如 QPushButton 类提供了 4 个信号函数和 5 个 public slots 属性的槽函数,可以满足大部分场景的需要。

实际开发中,可以使用 Qt 提供的信号函数和槽函数,也可以根据需要自定义信号函数和槽函数,我们会在《Qt自定义信号和槽函数》一节做详细介绍。

Qt Creator 提供了很强大的 Qt GUI 开发手册,很容易就能查到某个控件类中包含哪些信号函数和槽函数。举个例子,查看 QPushButton 类中信号函数和槽函数的过程是:

  1. 在程序中引入头文件,双击选中“QPushButton”并按 “Fn+F1” 快捷键,就会弹出 QPushButton 类的使用手册,如下图所示。

在这里插入图片描述

图 2 QPushButton类的使用说明

  1. 在 Contents 部分可以看到,QPushButton 类只提供了一些Public Slots属性的槽函数,没有提供信号函数。对于 QPushButton 类按钮,除了可以使用自己类提供的槽函数,还可以使用从父类继承过来的信号函数和槽函数。由图 2 可知,QPushButton 的父类是 QAbstractButton,点击 QAbstractButton 就可以直接跳转到此类的使用手册,如下图所示:

在这里插入图片描述

图 3 QPushButton父类使用说明

QAbstractButton 类中既有 Signals 信号函数,也有 Public Slots 槽函数,这里不再一一列举,感兴趣的读者可以自行查看。

注意,并非所有的控件之间都能通过信号和槽关联起来,信号和槽机制只适用于满足以下条件的控件:

控件类必须直接或者间接继承自 QObject 类。Qt 提供的控件类都满足这一条件,这里提供一张 Qt常用类的继承关系的高清图片,感兴趣的读者可以简单了解一下。

控件类中必须包含 private 属性的 Q_OBJECT 宏。

将某个信号函数和某个槽函数关联起来,需要借助 QObject 类提供的

connect() 函数。

connect()函数实现信号和槽

connect() 是 QObject 类中的一个静态成员函数,专门用来关联指定的信号函数和槽函数。

关联某个信号函数和槽函数,需要搞清楚以下 4 个问题:

信号发送者是谁?
哪个是信号函数?
信号的接收者是谁?
哪个是接收信号的槽函数?

仍以实现“按下按钮后窗口关闭”为例,先创建一个窗口和一个按钮,如下所示:

QWidget widget;
//定义一个按钮,它位于 widget 窗口中
QPushButton But("按钮控件",&widget);
信号发送者是 But 按钮对象,要发送的信号是“按钮被点击”,可以用 QPushButton 类提供的 clicked() 信号函数表示;信号的接收者是 widget 主窗口对象,“窗口关闭”作为信号对应的槽,可以用 QWidget 类提供的 close() 函数表示。

在 Qt5 版本之前,connect() 函数最常用的语法格式是:

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

各个参数的含义分别是:

sender:指定信号的发送者;
signal:指定信号函数,信号函数必须用 SIGNAL() 宏括起来;
reveiver:指定信号的接收者;
method:指定接收信号的槽函数,槽函数必须用 SLOT() 宏括起来; type
用于指定关联方式,默认的关联方式为 Qt::AutoConnection,通常不需要手动设定。

用 connect() 函数将 But 按钮的 clicked() 信号函数和 widget 窗口的 close() 槽函数关联起来,实现代码如下:

connect(&But, SIGNAL(clicked()), &widget, SLOT(close()));

如此就实现了“按下按钮会关闭窗口”的功能。

Qt5 版本中,connect() 函数引入了新的用法,常用的语法格式是:

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

和旧版本相比,新版的 connect() 函数改进了指定信号函数和槽函数的方式,不再使用 SIGNAL() 和 SLOT() 宏。

例如,用新版 connect() 函数关联 But 按钮的 clicked() 信号函数和 widget 窗口的 close() 槽函数,实现代码为:

connect(&But, &QPushButton::clicked, &widget, &QWidget::close);

可以看到,新版 connect() 函数指定信号函数和槽函数的语法格式是&+函数所在类+函数名。

一个 connect() 函数只能关联一个信号函数和一个槽函数,程序中可以包含多个 connect() 函数,能实现以下几种效果:

关联多个信号函数和多个槽函数;

一个信号函数可以关联多个槽函数,当信号发出时,与之关联的槽函数会一个接一个地执行,但它们执行的顺序是随机的,无法人为指定哪个先执行、哪个后执行;

多个信号函数可以关联同一个槽函数,无论哪个信号发出,槽函数都会执行。

此外,connect() 函数的 method 参数还可以指定一个信号函数,也就是说,信号之间也可以相互关联,这样当信号发出时,会随之发出另一个信号。

实例演示信号和槽机制

创建一个不含 ui 文件的 Qt Widgets Application 项目,只保留 main.cpp 源文件,删除 mainwindow.h 和 mainwindow.cpp 文件。在 main.cpp 文件中编写如下代码:

#include <QApplication>
#include <QWidget>
#include <QPushButton>
int main(int argc, char *argv[])
{QApplication a(argc, argv);//添加窗口QWidget widget;//定义一个按钮,它位于 widget 窗口中QPushButton But("按钮控件",&widget);//设置按钮的位置和尺寸But.setGeometry(10,10,100,50);//信号与槽,实现当用户点击按钮时,widget 窗口关闭QObject::connect(&But,&QPushButton::clicked,&widget,&QWidget::close);//让 widget 窗口显示widget.show();return a.exec();
}

运行结果为:

在这里插入图片描述

如上图所示,由于使用了 conect() 函数将 But 的 clicked() 信号函数和 widget 的 close() 槽函数关联起来,所以生成了“点击按钮后主窗口关闭”的效果。


http://chatgpt.dhexx.cn/article/IcMvK1sN.shtml

相关文章

Qt信号与槽机制

一. 简介 就我个人来理解&#xff0c;信号槽机制与Windows下消息机制类似&#xff0c;消息机制是基于回调函数&#xff0c;Qt中用信号与槽来代替函数指针&#xff0c;使程序更安全简洁。 信号和槽机制是 Qt 的核心机制&#xff0c;可以让编程人员将互不相关的对象绑定在一起&…

Qt --- 信号与槽

信号与槽概述 信号与槽是 Qt 框架引以为豪的机制之一。所谓信号与槽&#xff0c;实际就是观察者模式(发布-订阅模式)。当某个事件发生之后&#xff0c;比如&#xff0c;按钮检测到自己被点击了一下&#xff0c;它就会发出一个信号&#xff08;signal&#xff09;。这种发出是没…

Qt中的信号和槽详解

一、背景介绍 信号和槽用于两个对象之间的通信。信号和槽机制是Qt的核心特征&#xff0c;也是Qt不同于其他开发框架的最突出特征。在GUI编程中&#xff0c;当改变了一个部件时&#xff0c;总希望其他部件也能了解到该变化。更一般来说&#xff0c;我们希望任何对象都可以和其他…

QT笔记(一)

学习目标&#xff1a; 总结学习的QT 学习内容&#xff1a; 1、 QT的一些固定格式 2、 控件和事件 3、 信号和槽 记录内容&#xff1a; 1、 QT的固定格式 (1) 引用头文件 自己创建的头文件用" "括起&#xff0c;eg: #include "mainwindow.h"QT提供的头文…

QT中信号和槽详解

一、QT中信号和槽的机制 1、贴图来理解信号和槽的关系 2、解释 &#xff08;1&#xff09;信号和槽是用于QT对象之间的通信&#xff0c;信号可以有某种动作触发&#xff0c;也可以直接由代码触发。 &#xff08;2&#xff09;槽也叫操函数&#xff0c;当完成了信号和槽的连接…

Qt核心特性之 —— 「信号(Signal)与槽(Slot)」机制

目录 1、Qt 与 Qt Creator简介&#xff1a; 2、关于引用头文件的一些事儿&#xff1a; 3、信号(Signal)与槽(Slot)机制&#xff1a; 3.1、一个小例子&#xff1a; 4、自定义信号与槽&#xff1a; 4.1、运行效果&#xff1a; 5、信号与槽的特性&#xff1a; 6、Qt 4…

三张图搞定TCP 握手、HTTPS、TLS加密过程

1. 抓包内容&#xff08;WireShark&#xff09; 2. 搞定握手、挥手、SSL加密过程 3. 消息内容&#xff08;Charles&#xff09; 之前看到写的比较好的文章&#xff0c;有文字详细叙述&#xff1a; TLS版本差异 https://zhuanlan.zhihu.com/p/27524995?utm_source协议解析 htt…

TCP三次握手学习心得

客户端A若要连接服务端B&#xff0c;首先A会向B发送一个连接请求&#xff0c;其中SYN1&#xff0c;ACK0&#xff0c;B为了告诉A成功收到了消息&#xff0c;则向A发送一个确认包&#xff0c;其中SYN1,ACK1,这时A收到之后又会向B发送一个确认收到确认包的确认包&#xff0c;SYN0,…

使用wireshark抓取Tcp三次握手

文章目录 wireshark的下载安装TCP协议段格式简单介绍确认应答机制介绍使用wireshark抓取TCP的三次握手 wireshark的下载安装 软件的下载可以直接去官网下载 wireshark&#xff0c;选择自己电脑适合的版本就行。 但是不咋推荐&#xff0c;原因是国外网站访问速度太慢&#xff…

TCP的三次握手、四次挥手

一、TCP的三次握手 第一次握手&#xff1a;你能和我建立连接吗&#xff0c;可以接受到我的数据吗。 SYN 1 &#xff0c;seq x 第二次握手&#xff1a;可以建立连接&#xff0c;我接受到你的请求了&#xff0c;能接受到我的数据吗&#xff0c;你的数据是这个吗 SYN 1 &#…

TCP三次握手原理

在众多的网络协议中&#xff0c;TCP协议占据着举足轻重的地位&#xff0c;你知道什么是TCP协议吗&#xff1f; 一、TCP协议 TCP(Transmission Control Protoco)协议属于计算机网络体系中的运输层。运输层的任务是负责向主机中应用层进程之间的通信提供通用的数据传输服务。所以…

TCP三次握手及四次挥手过程中的异常处理

1. 消息丢失的情况&#xff1a; 总的原则&#xff1a; ACK不会重传&#xff0c;SYN和FIN报文段有最大重传次数。无论是SYN还是FIN&#xff0c;达到最大重传次数后对端若仍无响应则直接进入CLOSED状态。 1.1 三次握手过程的消息丢失&#xff1a; 正常的三次握手的流程&#x…

HTTPS 中 TLS 和 TCP 能同时握手吗?

HTTPS 中 TLS 和 TCP 能同时握手吗&#xff1f; 大家好&#xff0c;我是小林。 有位读者在面试的时候&#xff0c;碰到这么个问题&#xff1a; 面试官跟他说 HTTPS 中的 TLS 握手过程可以同时进行三次握手&#xff0c;然后读者之前看我的文章是说「先进行 TCP 三次握手&#…

TCP优化一:TCP 三次握手的优化

TCP 三次握手的性能提升 TCP 是面向连接的、可靠的、双向传输的传输层通信协议&#xff0c;所以在传输数据之前需要经过三次握手才能建立连接。 那么&#xff0c;三次握手的过程在一个 HTTP 请求的平均时间占比 10% 以上&#xff0c;在网络状态不佳、高并发或者遭遇 SYN 攻击…

TCP握手过程和挥手过程

TCP报文首部 源端口和目的端口&#xff0c;各占2个字节&#xff0c;分别写入源端口和目的端口&#xff1b;序号&#xff0c;占4个字节&#xff0c;TCP连接中传送的字节流中的每个字节都按顺序编号。例如&#xff0c;一段报文的序号字段值是 301 &#xff0c;而携带的数据共有1…

TCP三次握手

TCP协议是传输层协议&#xff0c;是一种面向连接的传输控制协议&#xff0c;可以控制流量的传输。是一种可靠的传输&#xff0c;能够保证数据的完整性&#xff0c;有效性和有序性。 1.TCP建立连接&#xff08;三次握手&#xff09; 第一次握手&#xff1a;PC1发送SYN请求&…

TCP握手与挥手详解(附有图)

为什么不是4次握手 首先我们知道TCP是3次握手与4次挥手&#xff0c;为什么不是4次握手呢&#xff0c;因为其中握手请求同步过程中并不需要数据传输因此将两次合并为一次了。 我们需要掌握哪些标志量 SYN&#xff1a;请求同步标志&#xff0c;为1的时候为有效 ACK&#xff1…

为什么TCP需要握手

一、TCP握手流程 二、为什么不是4次握手 TCP的每次请求都是成对的&#xff0c;原则上应该是四次 【Client to Server】第一次SYN&#xff0c;seqx【Server to Client】第二次ACK&#xff0c;seqy&#xff0c;ackx1&#xff08;没有携带数据的ACK不消耗序列号&#xff09;【Se…

tcp_tw_recycle引起的TCP握手失败

背景 测试环境的一台Nginx服务器&#xff0c;最近一直被前端同事吐槽网络有问题&#xff0c;经常出现访问HTTP请求时超时&#xff0c;哪怕是静态文件也经常超时。 刚开始以为是公司网络抽风了&#xff0c;也就没放在心上&#xff0c;但持续了一个星期&#xff0c;而且复现率很…

TCP握手过程(正解版)

参考文章 Why do we need a 3-way handshake? Why not just 2-way https://blog.csdn.net/qq_36903042/article/details/102656641 https://blog.csdn.net/qq_36903042/article/details/102513465 大部分网络博客的错误解读 首先需要声明的是&#xff0c; 百度搜索到的大…