【Qt】信号与槽

目录

一、信号与槽机制原理

1.1 概述

1.2 信号的本质

1.3 槽的本质

1.4 说明

二、信号和槽的使用

2.1 连接信号和槽

2.2 通过Qt Creator生成信号槽代码

三、自定义信号和槽

3.1 基本语法

3.2 带参数的信号和槽

四、信号和槽的其他说明

4.1 Qt4版本信号与槽的连接

4.2 信号与槽机制的优劣


一、信号与槽机制原理

1.1 概述

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

Qt中的所有控件都具有接收信号的能力,一个控件还可以接收多个不同的信号。对于接收到的每 个信号,控件都会做出相应的响应动作。在Qt中,对信号做出的响应动作就称之为槽。

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

1.2 信号的本质

信号(signal):信号的本质是事件。信号展示方式就是函数。当某一个事件发生后,就发出一个信号。

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

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

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

1.3 槽的本质

槽(slot):对信号相应的函数,槽就是一个函数。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。

1.4 说明

  1. 信号函数只需要声明,不需要定义(实现),槽函数需要定义(实现)。
  2. 信号和槽机制底层是通过信号之间相互调用实现的。每一个信号都可以用函数表示,称为信号函数;每个槽也可以用函数表示,称为槽函数。
  3. 信号函数用signals关键字修饰,槽函数用public slots、protected slots、private slots修饰。signals和slots是Qt在C++的基础上扩展的关键字,专门用来指明信号函数和槽函数。

二、信号和槽的使用

2.1 连接信号和槽

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

connect()函数原型:

connect (const QObject *sender,

               const char * signal ,

               const QObject * receiver ,

               const char * method ,

               Qt::ConnectionType type = Qt::AutoConnection )

参数说明:

  • sender:信号的发送者;
  • signal:发送的信号(信号函数);
  • receiver:信号的接收者;
  • method:接收信号的槽函数;
  • type:用于指定关联方式,默认的关联方式为Qt::AutoConnection,通常不需要手动设定。

信号和槽机制连接方式

  • 一个信号可以跟另一个信号相连;

conect(object1, signal1, object2, signal1);

  • 同一个信号可以跟多个槽相连;

conect(object1, signal2, object2, slot2);

conect(object1, signal2, object3, slot1);

  • 同一个槽可以响应多个信号;

conect(object1, signal2, object2, slot2);

conect(object3, signal2, object2, slot2);

常用连接方案采用:conect(object1, signal, object2, slot);

代码示例

系统自带的信号和槽通常是通过"Qt帮助文档"来查询。

2.2 通过Qt Creator生成信号槽代码

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

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

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

3、在 UI 设计窗口中拖入⼀个 "按钮" ,并且修改 "按钮" 的名称及字体大小等;

4、可视化生成槽函数

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

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

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

说明:

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

  1. 以" on "开头,中间使用下划线连接起来;
  2. " XXX "表示的是对象名(控件的 objectName 属性)。
  3. " SSS "表示的是对应的信号。 如:" on_pushButton_clicked() " ,pushButton 代表的是对象名,clicked 是对应的信号。

按照这种命名风格定义的槽函数,就会被Qt自动的和对应的信号进行连接。但是最好还是不要依赖命名规则,而是显式使用 connect 更好

2)在 "widget.cpp" 中自动生成槽函数定义.

6、在槽函数函数定义中添加要实现的功能.。实现关闭窗口的效果.


三、自定义信号和槽

3.1 基本语法

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

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

3、发送信号

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

示例1:

1、在 widget.h 中声明自定义的信号和槽,如图所示

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

注意:图中的 ① 和 ② 的顺序不能颠倒。原因是,首先关联信号和槽,一旦检测到信号发射之后就会立马执行关联的槽函数。反之,若先发射信号,此时还没有关联槽函数,当信号发射之后槽函数不会响应。

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

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

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

选择 "choose" 出现如下界面

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

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

在 teacher.h 中声明信号函数

在 student.h 中声明槽函数

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

在 student.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" 文件中实现槽函数以及连接信号和槽;


四、信号和槽的其他说明

4.1 Qt4版本信号与槽的连接

Qt4中的 connect 用法和Qt5相比是更复杂的。需要搭配 SIGNAL 和 SLOT 宏来完成。而且缺少必要的函数类型的检查。使代码更容易出错。

示例:

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

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

Qt4版本信号与槽连接的优缺点:

• 优点:参数直观;

• 缺点:参数类型不做检测;

4.2 信号与槽机制的优劣

优点:松散耦合。一个类若是要支持信号和槽,就必须从QObject或QObect的子类继承。Qt信号和槽机制不支持模板的使用。

缺点:效率较低。通过传递一个信号来调用槽函数会比直接调用非虚函数运行速度慢,主要原因:

  • 多线程的时候,信号可能需要排队
  • 编组/解组传递的参数
  • 安全地遍历所有关联
  • 需要定位接收信号的对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值