Signal & Slot 机制
什么是信号和槽?
用于完成界面操作的响应,是完成任意两个Qt对象之间的通信机制。
信号:某个特定情况或动作下被触发;
槽:接受并处理信号的函数;
包含内容
- 两个对象:信号的发送者和接收者;
- 发送者对象发送的信号:一个不需要去定义的空壳函数;
- 槽:接收者去执行的某个函数;
信号与槽机制优点
- 类型安全 :相连接的信号和槽的签名是等同的,即参数类型和个数一致(槽的参数个数可以少);
- 松散耦合 :信号发送者不需要去了解接收者的具体信息(有哪些接口等),回调函数,是紧密耦合,会直接调用目标对象的特定函数。
- 灵活 :使用起来更灵活;
信号槽与回调函数比较缺点
- 较回调函数的运送速度慢:信号与槽函数的执行可能是异步的(仅使用直连方式连接信号槽时,槽函数才会被同步执行,执行完之后,发送信号(emit)语句之后的代码才会被执行);
- 回调函数都是同步方式执行的,速度较快;
信号和槽的连接方式
界面自动连接:界面点击 【转到槽】;
代码手动连接:connect ();
(1)使用自动连接,点击转到槽,生成on_lineEdit_textChanged()
, 此时已完成部件信号与相应槽函数的连接,并且生成了这个信号槽函数,只需在里面开发相应的功能即可;
(2)使用connect()
以及信号和槽的定义宏, 前提要先创建好部件,并定义相应的槽函数
- 常用连接信号和槽(signal为对象1的信号,slot为对象2的槽)
connect(Object1, SIGNAL(signal), Object2, SLOT(slot));
- 两个不同信号相连(对象1的信号1发送可以触发对象2的信号1的发送)
connect(Object1, SIGNAL(signal1), Object2, SIGNAL(signal1));
- 同一个信号可以与多个槽相连
- 同一个槽可以响应多个信号
(3)使用函数指针:直接使用信号和槽函数的地址(无需添加参数) ,
connect(ui->lineEdittest,
&QLineEdit::textChanged, //直接引用地址
ui->label_4,
&QLabel::setText);
- 要求信号和槽的参数个数相同,而且能够进行合适的隐式类型转换;
- 信号和槽函数需要使用类名进行限定;
【注意】
-
定义自己的槽函数时,若声明不使用slots,那么用connect 连接只能使用引用&取信号和槽的地址,不能使用宏;(建议:自己定义槽函数加上slots)
-
SIGNAL( ) 和 SLOT( ) 是Qt定义的两个宏,它们返回其参数的C语言风格的字符串(const char*)。因此编程时
SIGNAL(clicked())
与"clicked()"
等同。 包含参数的规则:传递给SIGNAL()宏的参数不能少于SLOT()宏的参数
信号
信号的发送
信号分类
- 每个类预定义的信号:可通过查看官方文档获知使用;
- 自定义的信号:由开发人员自行定义;
信号的处理
- 当信号发出时,连接到它的槽函数通常会立即执行,此时机制完全独立于GUI事件循环的;
- emit 之后的代码将在所有槽函数都返回之后才执行;
名称 | 连接类型 | 含义 |
---|---|---|
直接连接 | Qt::DirectConnection | 当信号发出时,槽函数立即被调用,同步执行(使用emit发送信号后,槽函数被直接调用,调用完后再执行emit后的代码) |
队列连接 | Qt::QueuedConnection | 首先添加至信号队列,当控制返回到接收方线程的事件循环时,将调用槽函数执行(使用emit发送信号后,直接执行后面的代码,无需等待槽函数执行完毕) |
自动连接 | Qt::AutoConnection | 如果发送者与接受者处于同一线程:直接连接;若处于不同线程:队列连接(Qt默认的连接方式) |
阻塞连接 | Qt::BlockingQueuedConnection | 信号被触发后,发送者会阻塞,直到接收者处理完对应的槽函数;适用于处于不同线程但需要同步处理的情况 |
唯一连接 | Qt::UniqueConnection | 是一个标志,可以与上述连接类型进行按位与组合。可防止相同的信号重复发送 |
信号和槽传递自定义类型
同一个线程内使用信号和槽直接传递自定义类型;
但是在跨线程内使用时,需要先进行
qRegisterMetaType
注册类型;