一、簡單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