天天看點

【pyqt5】——信号與槽

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