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() 槽函数关联起来,所以生成了“点击按钮后主窗口关闭”的效果。

Qt信号和槽机制详解相关推荐

  1. Qt信号与槽机制详解1-创建一个带信号和槽的例子

    目录 一.编译一个例子 1.hello.h中的内容 2.hello.cpp的内容 3.main.cpp中的内容 4.tutorial.pro内容 二.moc_hello.cpp文件 1.Q_OBJEC ...

  2. 学习QT之信号槽机制详解

    学习QT之信号槽机制详解 一.Qt信号槽机制 概念:信号槽是Qt框架引以为豪的机制之一.所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如:按钮检测到自己被点击了一下,它就会发出一个信号(sig ...

  3. C++框架_之Qt的信号和槽的详解

    目录 C++_之Qt的信号和槽的详解 1.概述 1.1对象树(子对象动态分配空间不需要释放) 2.信号和槽 Qt5 的书写方式:(推荐的使用)★★★★★ Qt4 的书写方式: 3.自定义信号槽 3.1 ...

  4. Qt 信号和槽机制 优点 效率的详解

    一.信号和槽机制 Qt提供了信号和槽机制用于完成界面操作的响应,是完成任意两个Qt对象之间的通信机制. 其中,信号会在某个特定情况或动作下被触发,槽是等同于接收并处理信号的函数. 二..信号和槽机制的 ...

  5. QT信号与槽机制需要注意的问题

    1.信号与槽的效率是非常高的,但是同真正的回调函数比较起来,由于增加了灵活性,因此在速度上还是有所损失.当然这种损失相对来说是比较小的,但是要追求高效率的话,比如实时系统,就要尽可能避免. 2.信号与 ...

  6. Qt信号槽机制详解及案例

    目录 信号槽 标准信号槽 自定义信号槽 信号槽 信号槽是Qt框架引以为豪的机制之一.所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signa ...

  7. QT信号和槽机制分析

    QObject这个class是QT对象模型的核心,绝大部分的 QT 类都是从这个类继承而来.这个模型的中心特征就是一个叫做信号和槽(signal and slot)的机制来实现对象间的通讯,你可以把一 ...

  8. Qt基础之四:Qt信号与槽机制原理及优缺点

    目录 一.简介 二.信号和槽 三.信号(signals) 四.槽(slots) 五.在Qt中使用第三方的Signals和Slots 信号

  9. c++基础学习之QT 信号和槽机制的底层实现

    Qt 信号槽的实现 - DevBean Tech World Qt 的信号槽和属性系统基于在运行时进行内省的能力,内省意味着,我们可以列出对象的方法和属性列表,并且能够获取有关它们的所有信息,例如其参 ...

  10. Qt中事件循环机制详解

    问题1:Qt中常见的事件有哪些? 答:鼠标事件(QMouseEvent).键盘事件(QKeyEvent).绘制事件(QPaintEvent).窗口尺寸改变(QResizeEvent).滚动事件(QSc ...

最新文章

  1. 数据处理遇到麻烦不要慌,5个优雅的Numpy函数助你走出困境
  2. 有没有想过,自己手写一个连接池?
  3. HDU 1301 Jungle Roads(裸最小生成树)
  4. iphone4/iphone5/iphone6/iphone6Plus响应式布局适配代码
  5. numpy归一化_使用numpy 高效实现K-Means聚类
  6. vue html5 picker,基于vue的picker组件
  7. 现代软件工程 作业 团队第一个作业
  8. hugo_如何将Hugo用于教室的开源CMS
  9. MFC:ID命名和数字约定
  10. eclipse创建springboot项目的三种方法
  11. 前端工程化知识要点回顾思考
  12. Maven -- dependency详解
  13. linux - ab测试工具
  14. 论文翻译:2020_Improving Perceptual Quality By Phone-Fortified Perceptual Loss For Speech Enhancement...
  15. c语言max比较字符串,c语言中能不能用max函数求三个数的最大者呢?
  16. 面试算法:利用堆栈计算逆向波兰表达式
  17. 基于Femu搭建ZNS
  18. 用java编译实现计算个人所得税(工资)
  19. Twincat NC PTP
  20. 计算机辅助翻译翻译技术的译前应用,计算机辅助翻译技术在网络字幕组中的应用...

热门文章

  1. 瑞星linux病毒库位置,瑞星杀毒软件V16+怎样离线升级病毒库 病毒库离线升级办法...
  2. ubuntu下使用锐捷
  3. 有关设计网站的收藏集合
  4. 省市区随机获取 java_随机获取省市区-Groovy
  5. windows安装MySQL详细步骤
  6. 清华EMBA课程系列思考之十七(1) -- 新企业的孵化与创业投资
  7. 软考高项之项目变更管理
  8. html页面跳转及回退的几种方式
  9. android实现截图功能吗,android截屏功能实现代码
  10. termux配置python安装kali_利用termux安装kali