1. 程式人生 > >PyQt訊號與槽之訊號與槽的高階玩法(三)

PyQt訊號與槽之訊號與槽的高階玩法(三)

高階自定義訊號與槽

所謂高階自定義訊號與槽,指的就是我們可以以自己喜歡的方式定義訊號與槽函式,並傳遞引數,自定義訊號的一般流程如下

  • 定義訊號
  • 定義槽函式
  • 連線訊號與槽函式
  • 發射訊號

1 定義訊號

通過類成員變數定義訊號物件

    #無引數的訊號
    signal1=pyqtSignal()
    #帶一個引數(整數)的訊號
    signal2=pyqtSignal(int)
    #帶兩個引數(整數,字串)的訊號
    signal3=pyqtSignal(int,str)
    #帶一個引數(列表)的訊號
    signal4=pyqtSignal(list)
    #帶一個引數(字典)的訊號
signal5=pyqtSignal(dict) #帶(整數 字串)或者(字串)的訊號 signal6=pyqtSignal([int,str],[str])

2 定義槽函式

定義一個槽函式,它有多個不同的輸入參輸數

    def signalCall1( self ):
        print("signal1 emit")
    def signalCall2( self,val ):
        print('signal2 emit,value:',val)
    def signalCall3( self,val,text ):
        print('signall3 emit,value:'
,val,text) def signalCall4( self,val ): print('signal4 emit,value:',val) def signalCall5( self,val ): print('signal5 emit,value',val) def signalCall6( self,val,text ): print('signal6 emit,value',val,text) def signalCall7( self,val ): print('signal6 ovetload emit'
,val)

3 連線訊號與槽函式

        #訊號與槽函式的連結
        self.signal1.connect(self.signalCall1)
        self.signal2.connect(self.signalCall2)
        self.signal3.connect(self.signalCall3)
        self.signal4.connect(self.signalCall4)
        self.signal5.connect(self.signalCall5)
        self.signal6[int,str].connect(self.signalCall6)
        self.signal6[str].connect(self.signalCall7)

4 發射訊號

        #訊號發射
        self.signal1.emit()
        self.signal2.emit(1)
        self.signal3.emit(1,'第三個')
        self.signal4.emit([1,2,3,4])
        self.signal5.emit({"name":'JIA','age':'21'})
        self.signal6[int,str].emit(1,"第六")
        self.signal6[str].emit('第六')

5 例項

完整程式碼如下

from PyQt5.QtCore import QObject,pyqtSignal

class CusSignal(QObject):
    #無引數的訊號
    signal1=pyqtSignal()
    #帶一個引數(整數)的訊號
    signal2=pyqtSignal(int)
    #帶兩個引數(整數,字串)的訊號
    signal3=pyqtSignal(int,str)
    #帶一個引數(列表)的訊號
    signal4=pyqtSignal(list)
    #帶一個引數(字典)的訊號
    signal5=pyqtSignal(dict)
    #帶(整數 字串)或者(字串)的訊號
    signal6=pyqtSignal([int,str],[str])

    def __init__(self,parent=None):
        super(CusSignal, self).__init__(parent)

        #訊號與槽函式的連結
        self.signal1.connect(self.signalCall1)
        self.signal2.connect(self.signalCall2)
        self.signal3.connect(self.signalCall3)
        self.signal4.connect(self.signalCall4)
        self.signal5.connect(self.signalCall5)
        self.signal6[int,str].connect(self.signalCall6)
        self.signal6[str].connect(self.signalCall7)

        #訊號發射
        self.signal1.emit()
        self.signal2.emit(1)
        self.signal3.emit(1,'第三個')
        self.signal4.emit([1,2,3,4])
        self.signal5.emit({"name":'JIA','age':'21'})
        self.signal6[int,str].emit(1,"第六")
        self.signal6[str].emit('第六')

    #槽函式
    def signalCall1( self ):
        print("signal1 emit")
    def signalCall2( self,val ):
        print('signal2 emit,value:',val)
    def signalCall3( self,val,text ):
        print('signall3 emit,value:',val,text)
    def signalCall4( self,val ):
        print('signal4 emit,value:',val)
    def signalCall5( self,val ):
        print('signal5 emit,value',val)
    def signalCall6( self,val,text ):
        print('signal6 emit,value',val,text)
    def signalCall7( self,val ):
        print('signal6 ovetload emit',val)

if __name__ == '__main__':
    custSignal=CusSignal()

執行結果如下
這裡寫圖片描述

自定義引數的傳遞

在pyqt程式設計過程中,經常會遇到給槽函式傳遞自定義引數的情況,比如有一個訊號與槽函式的連線是

button.clicked.connect(show_page)

我們知道對於clicked訊號,它是沒有引數的,對於show_page函式來說,希望他可以接受引數,希望show_page函式如下這樣

def show_page(self,name):
    print(name',點選了’)

於是就會產生一個問題,訊號發出的引數個數與槽函式接受的引數個數不一,那麼如何解決這個問題呢,這裡提供兩種解決方法;
第一種:lamdba表示式
第二種:使用functools中的partial函式
兩種方法,下面均已寫上,自己可執行檢視,注意註釋
例項如下

import sys
from PyQt5.QtWidgets import *
from functools import partial

class WinForm(QMainWindow):
    def __init__(self,parent=None):
        super(WinForm, self).__init__(parent)
        #例項化兩個按鈕
        button1=QPushButton('Button1')
        button2=QPushButton('Button2')

        #todo 第一種方法
        #單擊訊號關聯槽函式,利用Lanbda表示式傳遞一個引數
        # button1.clicked.connect(lambda :self.onButtonClick(1))
        # button2.clicked.connect(lambda :self.onButtonClick(2))
        #
        #todo 第二種方法
        button1.clicked.connect(partial(self.onButtonClick, 1))
        button2.clicked.connect(partial(self.onButtonClick, 2))

        #例項化視窗
        main=QWidget()

        #設定視窗的佈局,並向其中新增控制元件
        layout=QHBoxLayout(main)
        layout.addWidget(button1)
        layout.addWidget(button2)

        #設定為中央控制元件
        self.setCentralWidget(main)
    def onButtonClick( self,n ):

        #彈窗資訊提示框,輸出被點選的資訊
        print("Button {0}".format(n))
        QMessageBox.information(self,'資訊提示框','Button {0}'.format(n))
if __name__ == '__main__':
    app=QApplication(sys.argv)
    form=WinForm()
    form.show()
    sys.exit(app.exec_())

執行效果如圖所示
這裡寫圖片描述這裡寫圖片描述

程式碼分析

重點解釋
使用lambda表示式傳遞按鈕數字給槽函式,當然還可以傳遞其他東西,甚至是按鈕本身

button1.clicked.connect(lambda :self.onButtonClick(1))
button2.clicked.connect(lambda :self.onButtonClick(2))

另一種方法是使用functools中的partial函式

button1.clicked.connect(partial(self.onButtonClick, 1))
button2.clicked.connect(partial(self.onButtonClick, 2))