【C++ • QT】信号与槽机制原理、用法、实现方法

前言

本文详细介绍 QT 中信号与槽机制的原理、用法、实现方式。

一、QT 信号与槽机制原理

1、什么是信号

信号:信号本质是事件,在 Qt 中信号以函数形式呈现。当特定事件发生时,对象会发出对应的信号。常见触发信号的场景包括:

  • 界面元素操作(按钮点击、复选框切换)
  • 窗口状态变化(窗口刷新、关闭)
  • 系统事件(鼠标移动、键盘输入)
  • 数据变化(列表项添加、模型数据更新)

2、什么是槽

:槽是用于响应信号的特殊函数,与一般的函数不同,槽函数可以通过connect()与信号关联。当关联的信号被发射时,槽函数会被自动调用。槽函数需要用户手动实现,其定义方式与普通成员函数类似,但需要使用特定的声明语法。

3、信号与槽连接方式

信号与槽的关联通过QObject::connect()函数实现,Qt 提供了多种重载形式:

// Qt4风格(基于字符串的连接)
QMetaObject::Connection QObject::connect(
    const QObject *sender, 
    const char *signal,
    const QObject *receiver, 
    const char *method, 
    Qt::ConnectionType type = Qt::AutoConnection
);

// Qt5风格(基于函数指针的连接)
QMetaObject::Connection QObject::connect(
    const QObject *sender, 
    PointerToMemberFunction signal,
    const QObject *receiver, 
    PointerToMemberFunction method,
    Qt::ConnectionType type = Qt::AutoConnection
);

// Lambda表达式连接(Qt5+)
QMetaObject::Connection QObject::connect(
    const QObject *sender, 
    PointerToMemberFunction signal,
    const QObject *context, 
    const Functor &functor,
    Qt::ConnectionType type = Qt::AutoConnection
);

其中参数 sender 表示发出信号的对象,参数 signal 表示 sender 对象的信号,参数 receiver 表示信号接收者,参数 method 表示 receiver 对象的槽函数,当检测到 sender 信号, receiver 对象调用 method 方法。第五个参数 typeQt::ConnectionType 枚举,里面提供了五种连接类型,默认为AutoConnection

  • Qt::AutoConnection(默认值):AutoConnection会根据发送者和接收者所在的线程自动选择连接方式。如果信号和槽在同一线程,使用 DirectConnection,如果信号和槽在不同线程,使用 QueuedConnection。大多数情况都直接使用默认值
  • Qt::DirectConnection:当信号发射时,槽函数直接执行。槽函数在信号发射者的线程中执行,不会经历事件循环,可能导致线程安全问题。当信号与槽在同一线程并且需要立刻响应时可以使用DirectConnection
  • Qt::QueuedConnection:当信号发射后,槽函数不会立刻执行,会放入接收者线程的事件队列中,等待该线程处理事件时执行。槽函数在接收者的线程中执行,可以避免跨线程直接调用,执行存在一定的延迟。在需要跨线程通信异步执行,需要保持线程安全时可以使用QueuedConnection
  • Qt::BlockingQueuedConnection:类似于 QueuedConnection,但信号发射后会堵塞当前线程,直到槽函数执行完毕。跨线程同步调用,可能会导致死锁(如果接收者和发送者在同一线程)。在需要等待槽函数执行结果的同步执行跨线程通信时可以使用BlockingQueuedConnection
  • Qt::UniqueConnection:与其他连接类型组合使用,确保同一对信号和槽之间只建立一次连接。可以避免重复连接导致槽函数被多次调用。

// 1. 默认连接(AutoConnection)
connect(sender, SIGNAL(valueChanged()), receiver, SLOT(updateValue()));

// 2. 直接连接(同一线程内立即执行)
connect(sender, SIGNAL(valueChanged()), receiver, SLOT(updateValue()), Qt::DirectConnection);

// 3. 队列连接(跨线程安全调用)
connect(sender, SIGNAL(valueChanged()), receiver, SLOT(updateValue()), Qt::QueuedConnection);

// 4. 阻塞队列连接(跨线程同步调用)
connect(sender, SIGNAL(valueChanged()), receiver, SLOT(updateValue()), Qt::BlockingQueuedConnection);

// 5. 唯一连接(防止重复连接)
connect(sender, SIGNAL(valueChanged()), receiver, SLOT(updateValue()), Qt::AutoConnection | Qt::UniqueConnection);

信号与支持多种连接方式:

  • 一个信号可以与另一个信号相连(信号触发信号)
	connect(Object1,SIGNAl(signal1),Object2,SIGNAL(signal1));
  • 同一个信号可以与多个槽相连(信号与槽)
	connect(Object1,SIGNAl(signal2),Obect2,SIGNAL(slot2));
	connect(Object1,SIGNAl(signal2),Object3,SIGNAL(slot1));
  • 同一个槽可以响应多个信号
	connect(Object1,SIGNAl(signal12),Object2,SIGNAL(slot2));
	connect(Object3,SIGNAl(signal12),Object2,SIGNAL(slot2));

  • 🚀 个人简介:优快云「博客新星」TOP 10 , C/C++ 领域新星创作者
  • 💟 作    者:锡兰_CC ❣️
  • 📝 专    栏:【OpenCV • c++】计算机视觉
  • 🌈 若有帮助,还请关注➕点赞➕收藏,不行的话我再努努力💪💪💪

更多专栏订阅推荐:

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锡兰_CC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值