一、簡單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-width:200px;min-width: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
==