一、信号和槽的创建
1.信号和槽的介绍
- 每一个QObject对象和所有继承自QWidget的控件(这些都是 QObject 的子对象)都支持信号与槽机制。
- 当信号发射时,连接的槽函数将会自动执行。
- 信号与槽通过object.signal.connect()方法连接。
信号与槽具有如下特点。
- 一个信号可以连接多个槽。
- 一个信号可以连接另一个信号。
- 信号参数可以是任何Python类型。
- 一个槽可以监听多个信号。
- 信号与槽的连接方式可以是同步连接,也可以是异步连接。
- 信号与槽的连接可能会跨线程。
- 信号可能会断
示意图:
API中信号与槽的更详细解释,可以参考官方网站:
2.定义信号
1> 为QObject对象创建信号
- 使用pyqtSignal()函数创建一个或多个重载的未绑定的信号作为类的属性,信号只能在QObject的子类中定义
- 信号必须在类创建时定义,不能在类创建后作为类的属性动态添加进来。
- 信号可以传递多个参数,并指定信号传递参数的类型,参数类型是 标准的Python数据类型(字符串、日期、布尔类型、数字、列表、元组和字典)
2> 为控件创建信号 - 为自定义控件WinForm创建了一个btnClickedSignal信号。
class WinForm(QMainWindow):
btnClickedSignal=pyqtSignal()
3.操作信号
- 使用connect()函数可以把信号绑定到槽函数上
- 使用disconnect()函数可以解除信号与槽函数的绑定
- 使用emit()函数可以发射信号
4.信号与槽的入门应用
1>内置信号与槽的使用
- 是指在发射信号时,使用窗口控件的函数,而不是自定义的函数。
- 代码
from PyQt5.QtWidgets import QPushButton, QApplication, QWidget
from PyQt5.QtWidgets import QMessageBox
import sys
app = QApplication(sys.argv)
widget = QWidget()
def showMsg() :
QMessageBox.information(widget, "信息提示框", "ok,弹出测试信息")
btn = QPushButton("测试点击按钮", widget)
btn.clicked.connect(showMsg)
widget.show()
sys.exit(app.exec_())
- 效果
2>自定义信号与槽的使用
- 指在发射信号时,不使用窗口控件的函数,而是使用自定义的函数(简单地说,就是使用 pyqtSignal 类实例发射信号)
- 代码
"""
【简介】
内置信号槽示例
"""
from PyQt5.QtCore import QObject, pyqtSignal
# 信号对象
class QTypeSignal(QObject) :
# # 定义一个信号
# sendmsg = pyqtSignal(object)
#定义含有两个参数的信号
sendmsg = pyqtSignal(str,str)
def __init__(self) :
super(QTypeSignal, self).__init__()
def run(self) :
# 发射信号
# # 传递一个参数
# self.sendmsg.emit('Hello Pyqt5')
# 传递两个参数
self.sendmsg.emit('第一个参数', '第二个参数')
# 槽对象
class QTypeSlot(QObject) :
def __init__(self) :
super(QTypeSlot, self).__init__()
# 槽对象里的槽函数
# def get(self, msg) :
# print("QSlot get msg => " + msg)
def get(self, msg1, msg2) :
print("QSlot get msg => " + msg1 + ' ' + msg2)
if __name__ == '__main__' :
send = QTypeSignal()
slot = QTypeSlot()
# 1
print('--- 把信号绑定到槽函数 ---')
send.sendmsg.connect(slot.get)
send.run()
# 2
print('--- 把信号断开槽函数 ---')
send.sendmsg.disconnect(slot.get)
send.run()
- 运行结果
3>装饰器的信号与槽的使用
- 是第一种的衍生,后面会介绍
5.自定义信号(pyqtSignal)的原理和方法
1> 基本原理
- 自定义信号是通过pyqtSignal函数以类属性的方式在被重写的类内部实现的,这里的类属性和实例属性一定要区分清楚,不能再pyqtSignal之前加self。
- pyqtSignal()函数也可以传递不同的参数。
2> 代码
- 思路:
自定义按钮类:
1.定义好一个信号
2.寻找这个信号所触发的事件
3.在事件内部调用父类功能事件+逻辑判断->通过emit函数把定义的信号发出去
定义窗口类:
1.init函数
2.func_list函数
3.对应func函数->内部定义槽函数+利用自定义信号connect连接
点击查看代码
from PyQt5.Qt import *
import sys
#自定义信号
class Btn(QPushButton) :
rightSignal = pyqtSignal() # 先定义好一个信号,然后寻找这个信号所属事件
#通过事件来触发,需要重写事件
def mousePressEvent(self, evt) :
super().mousePressEvent(evt) #调用父类功能
# print(evt.button()) # QMouseEvent
# if evt.button() == 2:
if evt.button() == Qt.RightButton :#左键是1 右键是2
# print('鼠标右键被按下') # 这是用来测试右键是否生效,不是槽函数功能
self.rightSignal.emit() # 通过emit函数来把之定义的信号发射出去,以实现后面与槽函数的连接
pass
class Window(QWidget) :
def __init__(self) :
super().__init__()
self.setWindowTitle("自定义信号的原理和方法")
self.resize(600, 500)
self.func_list()
def func_list(self) :
self.func()
def func(self) :
# btn = QPushButton(self)
btn = Btn(self)
btn.setText('按钮')
btn.move(200, 100)
#槽函数
def btn_press() :
print('鼠标被按下')
#btn.pressed.connect(btn_press) #内置信号pressed与槽函数连接,只有左键按时会有反应
btn.rightSignal.connect(btn_press) #用自定义信号连接槽函数,并把槽函数内的内容输出
if __name__ == '__main__' :
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
- 运行结果
右键点击按钮,输出