一、简单Demo
简单使用信号和槽(之前常用的使用方式):
class DemoWin(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.resize(400, 250) self.btn = QPushButton("发送信号", self) # 发送一个clicked信号,绑定槽函数是self.onClick() self.btn.clicked.connect(self.onClick) # 添加窗口标题 self.setWindowTitle("SignalDemo") # 槽函数,接收btn的clicked信号 def onClick(self): self.btn.setText("接收到信号") self.btn.setStyleSheet("max-200px;min-200px;")
这是最简单的信号和槽的使用方法,其中clicked事件是button的默认事件,我们将其绑定到自定义的onClick槽函数即可。
二、自定义信号Demo
# 导入信号 from PyQt5.QtCore import Qt, QObject, pyqtSignal # 自定义信号类 class MySignal(QObject): sendmsg = pyqtSignal(object) # 定义一个信号,object表示传递一个参数(object是python中的基类) def run(self): self.sendmsg.emit("Hello PyQt5") # 触发信号,并传递一个string参数 class MySlot(QObject): # 定义槽函数,接收一个string参数 def slot(self, msg): print("接收到的信息是:", msg) if __name__ == '__main__': mySignal = MySignal() mySlot = MySlot() # 将信号和槽进行绑定 mySignal.sendmsg.connect(mySlot.slot) #mySignal.sendmsg.disconnect(mySlot.slot) # 断开连接 # 触发信号 mySignal.run() # 打印 "接收到的信息是: Hello PyQt5"
1)首先创建一个pyqtSignal信号实例(参数对应槽的参数的类型)
2)使用connect绑定信号和槽(使用后可以手工断开连接,使用mySignal.sendmsg.disconnect(mySlot.slot))
3)触发信号
三、信号传递数据(多个参数)
# 导入信号 from PyQt5.QtCore import Qt, QObject, pyqtSignal # 自定义信号类 class MySignal(QObject): sendmsg = pyqtSignal(object, int, dict) # 定义一个信号,传递三个参数 def run(self): self.sendmsg.emit("Hello PyQt5", 50, {"name": "leo"}) # 触发信号,并传递三个参数,参数类型在信号定义时指定 class MySlot(QObject): # 定义槽函数,接收一个string参数 def slot(self, msg,age,name): print("接收到的信息是:", msg) print("接收到的年龄是:", age) print("接收到的名称是:", name['name']) if __name__ == '__main__': mySignal = MySignal() mySlot = MySlot() # 将信号和槽进行绑定 mySignal.sendmsg.connect(mySlot.slot) # 触发信号 mySignal.run() # 打印 "接收到的信息是: Hello PyQt5"
可以看到,我们在定义信号的时候指定了对应槽函数的参数类型,并在触发信号时传入实际的参数,这样槽函数就可以接受到数据了。
四、多对多绑定,绑定信号
信号和槽是可以N对N绑定的,也就是说在参数一致的情况下,一个信号可以绑定多个槽函数,一个槽函数也可以绑定多个信号。
信号还可以与信号绑定,例如B信号绑定了A信号,A信号和A槽函数绑定,则触发B最终触发A槽函数。
Demo:
# 导入信号 from PyQt5.QtCore import Qt, QObject, pyqtSignal # 自定义信号类 class MySignal(QObject): signal1 = pyqtSignal(object) signal2 = pyqtSignal(object,object) def __init__(self): super(MySignal, self).__init__() # signal1绑定多个槽函数(slot1和slot2) self.signal1.connect(self.slot1) self.signal1.connect(self.slot2) # signal2绑定signal1 self.signal2.connect(self.signal1) self.signal1.emit(1) # 触发slot1和slot2 self.signal2.emit(2,3) # 虽然目前signal2和signal1绑定,但是signal2.emit的参数还是必须和signal定义时一致 def slot1(self, num): print("slot1 " + str(num)) def slot2(self, num): print("slot2 " + str(num)) if __name__ == '__main__': mySignal = MySignal()
特别注意,signal2和signal1绑定后,槽函数的参数应该是signal1一致,而signal2.emit的参数应该是signal2定义时的参数类型一致。
signal2和signal1绑定时,触发signal2的参数个数要多余signal1。例如signal1有一个int参数,那么singal2的第一个参数也必须是int,后面多的参数没用。
上述代码的输出结果:
slot1 1 slot2 1 slot1 2 # 这里的2就是signal2传递给signal1的第一个参数,然后signal1将其传递给了slot1 slot2 2
==