信号与槽(Signal & Slot)是Qt编程的基础,也是Qt的一大创新。因为有了信号与槽的编程机制,在Qt中处理界面各个组件的交互操作时变得更加直观和简单。
本文对信号与槽的内容进行了直观地介绍,让你一文读懂信号与槽。
一、什么是信号与槽
信号(Signal)就是在特定情况下被发射的事件,例如PushButton常见的信号就是鼠标单击时发射的clicked()信号,而一个ComboBox最常见的信号是选择的列表项变化时发射的CurrentIndexChanged()信号。GUI程序设计的主要内容就是对界面各组件的信号响应,只要知道什么情况发射哪些信号,然后合理去响应和处理这些信号就好了。
槽(Slot)就是对信号响应的函数。与一般的C++函数一样,槽就是一个函数,可以定义在类的任何部分(如public、private或protected),可以具有任意参数,也可以被直接调用。与一般函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数自动被执行。
二、信号与槽如何关联
信号与槽的关联是用QObject::connect()函数实现的。connect()是QObject类的一个静态函数,而QObject是所有Qt类的基类。在实际调用时也可以忽略前面的限定符,直接调用connect。
(1)在Qt5之前的版本中connect的基本格式是:
QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));
其中sender是发射信号的对象名称,signal()是信号名称。信号可以看作是特殊的函数,需要带括号,有参数时需要指明参数。receiver是接收信号的对象名称,slot()是槽函数的名称。比如以下代码:
QObject::connect(pushButton, SIGNAL(clicked()), widget, SLOT(close()));
实现了“点击按钮关闭窗口”的功能。
(2)从Qt5.0版本开始,connect函数引入了新的用法(原来的方法正常使用),改进了指定信号函数和槽函数的方式,不再使用SIGNAL()和SLOT()宏,而是采用“&函数所在类名::函数名”的格式。比如上面的例子,
QObject::connect(pushButton, &QPushButton::clicked, widget, &QWidget::close);
(3)默认地,Qt在每一个setupUi函数中包含了如下的关联函数,
QMetaObject::connectSlotsByName(QObject *object);
功能是递归搜索给定object对象的所有子对象,并将来自这些子对象的匹配信号关联到以下形式的槽函数:“on_子对象名称_信号名”。比如你自己定义了一个函数,
void on_pushButton_clicked();
那么这个函数将作为槽函数自动关联到pushButton的clicked()信号,而不再需要显式地调用connect函数。
三、需要知道的一些规则
(1)一个信号可以关联多个槽,槽函数按照建立连接时的顺序依次执行。
(2)多个信号可以连接同一个槽,任意一个信号被发射时都会触发槽函数。
(3)一个函数被发射时,与其关联的槽函数通常被立即执行。只有当信号关联的所有槽函数都执行完毕后,才会执行发射信号处后面的代码。
(4)一个信号可以连接另外一个信号,只需将SLOT(slot())替换为被连接的信号SINGAL(signal2())。这样,当一个信号被发射时,也会发射另外一个信号,实现某些特殊的功能。
(5)严格来讲,信号与槽的参数个数与类型要一致,至少信号参数不能少于槽的参数,否则会出错。
(6)使用信号与槽的类,必须在类的定义中加入宏Q_OBJECT。
(7)信号函数只需要声明,不需要定义(实现),而槽函数需要定义(实现)。
(8)为了提高开发效率,Qt 的各个控件类都提供了一些常用的信号函数和槽函数。
(9)实际开发中,可以使用 Qt 提供的信号函数和槽函数,也可以根据需要自定义信号函数和槽函数。
看了本文,你对Qt的信号与槽了解了吗?欢迎大家多多关注评论转发!