QT->信号与槽详解上(概述、使用、自定义、连接方式、其他说明)

一、信号和槽概述

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

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

信号和槽是Qt特有的消息传输机制,可以通过connect这样的函数,把一个信号和一个槽这种相互独立的控件关联起来。比如,"按钮"和"窗口"本身是两个独立的控件,点击"按钮"并不会对"窗口"造成任何影响。通过信号和槽机制,可以将"按钮"和"窗口"关联起来,实现"点击按钮会使窗口关闭"的效果

1、信号本质

信号是由于用户对窗口或控件进行了某些操作,导致窗口或控件产生了某个特定事件,这时Qtr对应的窗口类会发出某个信号,以此对用户的操作做出反应。因此,信号的本质就是事件。

  • 按钮单击、双击
  • 窗口刷新
  • 鼠标移动、鼠标按下、鼠标释放
  • 键盘输入

那么再Qt中信号是通过什么形式呈现给使用者的呢?

  • 我们对哪个窗口进行操作,哪个窗口就可以捕捉到这些被触发的事件
  • 对于使用者来说触发了一个事件,我们就可以得到Qt框架给我们发出的某个特定信号
  • 信号的呈现形式就是函数,也就是说某个事件产生了,Qt框架就会调用某个对应的信号函数,通知使用者

在Qt中信号的发出者是某个实例化的类对象

2、槽的本质

槽(Slot)就是对信号响应的函数 。槽就是一个函数,与一般的C++函数是一样的,可以定义在类的任何位置(public、protected或private),可以具有任何参数,也可以被重载,也可以被直接调用(但是不能有默认参数)

槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行

所谓的槽函数本质上也是一种回调函数

【C语言阶段 - 函数指针】

  1. 实现转移表,降低代码的"圈复杂度"
  2. 实现回调函数效果(qsort)

【C++阶段】

  1. STL中,函数对象/坊函数
  2. lambda表达式

【Linux】

  1. 信号处理函数
  2. 线程的入口函数
  3. epoll基于回调的机制

(1)连接信号和槽机制底层是通过函数间的相互调用实现的

每个信号都可以用函数来表示,称为信号函数 ;每个槽也可以用函数表示,称为槽函数

例如:"按钮被按下"这个信号可以用cicked()函数表示,"窗口关闭"这个槽可以用close()函数表示,假如使用信号和槽机制 - 实现:"点击按钮会关闭窗口"的功能,其实就是clicked()函数调用close()的效果

(2)信号函数和槽函数通常位于某个类中

和普通的成员函数相比,它们的特别之处:

  • **信号函数用signals关键字修饰,槽函数用public slots、protected slots或者private slots修饰。**signals和slots是Qt在C++的基础上扩展的关键字,专门用来指明信号函数和槽函数
  • 信号函数只需要声明,不需要定义(实现),而槽函数需要定义(实现)

信号函数的定义是Qt自动在编译程序之前生成的,我们编写Qt应用程序无需关注这个,这种**自动生成代码的机制称为"元编程",**这种操作在很多场景中都能见到

二、信号和槽的使用

1、连接信号和槽

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

(1)关于QObject

QObject是Qt内置的父类,Qt中提供的很多类都是直接或者间接继承自QObject。

(2)connect()

A.函数原型

cpp 复制代码
           //描述当前信号是哪个控件发出的
connect (const QObject *sender,    
        //信号类型
        const char * signal ,     
        //信号如何处理(哪个对象处理)
        const QObject * receiver , 
        //信号如何处理(这个对象该怎么处理------要处理信号的对象提供的成员函数)
        const char * method ,      
        //暂时不考虑,很少使用
        Qt::ConnectionType type = Qt::AutoConnection ) 

B.参数说明

  • sender:信号的发送者
  • signal:发送的信号(信号函数)
  • receiver:信号的接收者
  • method:接收信号的槽函数
  • type:用于指定关联方式

c.代码示例

在窗口设置一个按钮,当点击"按钮"时关闭"窗口"

2、查看内置信号和槽

系统自带的信号和槽通常时通过"Qt帮助文档 "来查询的。如上述示例,要查询按钮的信号,在帮助文档输入:QpushButton 首先可以在"contents "中寻找关键字signals ,如果没有找到,继续去父类中查找,因此我们去他的父类QAbstractButton 中继续查找关键字signals

这里的clicked()就是我们要找的信号。槽函数的寻找方式和信号一样,只不过他的关键字时slots

3、通过Qt Creator生成信号槽代码

Qt Create 可以快速帮助我们生成信号槽相关的代码

代码示例:在窗口中设置一个按钮,当点击按钮时关闭窗口

(1)新建项目,如下图为新建完成之后所包含的所有文件

(2)双击widget.ui文件,进入UI设计界面

(3)在UI设计窗口中拖入一个按钮,并且修改按钮的名称及字体大小

(4)可视化生成槽函数

当鼠标单机"转到槽..."之后,出现如下界面:对于按钮来说,当点击时发送信号是clicked(),所以此处选择:clicked()

这个窗口列出了QPushButton给我们提供的所有信号(还包含了QPushButton父类的信号)

对于普通按钮来说,使用clicked信号即可

clicked(bool)没有意义的,具有特殊状态的按钮(比如:复选按钮)才会用到clicked(bool)

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

A.在"widget.h"头文件中自动添加槽函数的声明

说明:自动生成槽函数的名称有一定的规则,槽函数的命名规则为:on_xxx_sss,其中:

以"**on"**开头,中间使用下划线连接起来

"xxx "表示的是对象名(控件的objectName属性)

"sss" 表示的是对应的信号

如:"on_pushButton_clicke d()",pushButton代表的是对象名,clicked是对应的信号。按照i这种命名风格定义的槽函数,就会被Qt自动的和对应的信号进行连接。但是我们日常写代码的时候,除非是IDE自动生成,否则最好还是不要去依赖命名规则,而是显示使用connect更好

  • 一方面,显示connect可以更清晰直观的描述信号和槽的连接关系
  • 另一方面,也是防止信号或者槽的名字拼写错误导致连接失败

当然,是配置大于约定,还是约定大于配置,那种更好。这样的话题业界桑存在争议,这里我个人还是建议优先考虑显示connect()

B.在widget.cpp中自动生成槽函数定义

(6)在槽函数函数定义中添加要实现的功能,实现关闭窗口的效果

相关推荐
深耕AI2 小时前
【VS Code 中 Python 虚拟环境降级完整指南(含 uv 工具实战)】
开发语言·python·uv
小CC吃豆子2 小时前
C/C++中 int 的最大最小值
c语言·开发语言·c++
Bert.Cai2 小时前
pymysql自动提交设置
开发语言·python
欧米欧2 小时前
C++模板初阶
开发语言·c++
酉鬼女又兒2 小时前
零基础快速入门前端蓝桥杯Web考点深度解析:var、let、const与事件绑定实战(可用于备赛蓝桥杯Web应用开发)
开发语言·前端·javascript·职场和发展·蓝桥杯·es6·html5
IT从业者张某某2 小时前
Dockerfile详解
java·开发语言
南境十里·墨染春水2 小时前
C++笔记 类模板(面向对象)
开发语言·c++·笔记
小白学大数据2 小时前
攻克滑动拼图反爬:Python 高效爬取网页图片实战案例
开发语言·爬虫·python
煜磊2 小时前
C/C++语言部署安装_C/C++Api学习
开发语言·c++