Qt信号槽机制理解

1. 信号和槽概述

> 信号槽是 Qt 框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式(发布-订阅模式)。当某个`事件`发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。

1.1 信号的本质

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

因此根据上述的描述我们得到一个结论:信号的本质就是事件,比如:

  • 按钮单击、双击

  • 窗口刷新

  • 鼠标移动、鼠标按下、鼠标释放

  • 键盘输入

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

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

在QT中信号的发出者是某个实例化的类对象,对象内部可以进行相关事件的检测。

1.2 槽的本质

在Qt中槽函数是一类特殊的功能的函数,在编码过程中也可以作为类的普通成员函数来使用。之所以称之为槽函数是因为它们还有一个职责就是对Qt框架中产生的信号进行处理。

举个简单的例子:

女朋友说:“我肚子饿了!”,于是我带她去吃饭。

上边例子中相当于女朋友发出了一个信号, 我收到了信号并其将其处理掉了。

  • 女朋友 -> 发送信号的对象, 信号内容: 我饿了
  • 我 -> 接收信号的对象并且处理掉了这个信号, 处理动作: 带她去吃饭

在Qt中槽函数的所有者也是某个类的实例对象。

1.3 信号和槽的关系

在Qt中信号和槽函数都是独立的个体,本身没有任何联系,但是由于某种特性需求我们可以将二者连接到一起,相当于一个绑定,在Qt中我们需要使用QOjbect类中的connect函数进二者的关联。

QMetaObject::Connection QObject::connect(
    	const QObject *sender, PointerToMemberFunction signal, 
        const QObject *receiver, PointerToMemberFunction method, 
		Qt::ConnectionType type = Qt::AutoConnection);
- 参数:
	- sender: 发出信号的对象
	- signal: 属于sender对象, 信号是一个函数, 这个参数的类型是函数指针, 信号函数地址
    - receiver: 信号接收者
	- method: 属于receiver对象, 当检测到sender发出了signal信号, 
              receiver对象调用method方法,信号发出之后的处理动作
                  
// connect函数相对于做了信号处理动作的注册
// 调用conenct函数的sender对象的信号并没有产生, 因此receiver对象的method也不会被调用
// method槽函数本质是一个回调函数, 调用的时机是信号产生之后, 调用是Qt框架来执行的
// connect中的sender和recever两个指针必须被实例化了, 否则conenct不会成功
connect(const QObject *sender, &QObject::signal, 
        const QObject *receiver, &QObject::method);

1.4 通过实例加深理解

  • 现在要实现一个简单的功能,就说创建一个按钮,点击这个按钮关闭窗口

然后思考,这个功能的信号发出者,信号接受者,以及发出什么信号,接受信号后怎么做

  • 按钮: 信号发出者 -> QPushButton
  • 窗口: 信号的接收者和处理者 -> QWidget
  • 发出信号:被点击 -> clicked
  • 槽函数,即如何处理 -> close
  • 现在我们来实现一下

在ui中添加一个button,取名为closeBtn


然后再Mainwindow.cpp 文件中
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    connect(ui->closeBtn,&QPushButton::clicked,this,&MainWindow::close);
}

MainWindow::~MainWindow()
{
    delete ui;
}

注意这条语句
connect(ui->closeBtn,&QPushButton::clicked,this,&MainWindow::close);
通过这条语句来实现绑定

  • 现在我们来运行一下

点击按钮,窗口关闭

这只是一个很简单的例子,用来帮助理解信号槽,希望对你有帮助。

posted @ 2021-06-11 23:23  进击的汪sir  阅读(1232)  评论(0编辑  收藏  举报