PyQt訊號與槽之訊號與槽的高階玩法(三)
阿新 • • 發佈:2019-01-06
高階自定義訊號與槽
所謂高階自定義訊號與槽,指的就是我們可以以自己喜歡的方式定義訊號與槽函式,並傳遞引數,自定義訊號的一般流程如下
- 定義訊號
- 定義槽函式
- 連線訊號與槽函式
- 發射訊號
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))