Python Qt GUI设计:信号与槽的使用方法(基础篇—7)
目錄
1、信號與槽的概念
2、信號與槽的基礎(chǔ)函數(shù)
2.1、創(chuàng)建信號函數(shù)
2.2、連接信號函數(shù)
2.3、斷開信號函數(shù)
2.4、發(fā)射信號函數(shù)
3、信號和槽的使用方法
3.1、內(nèi)置信號與槽的使用
3.2、自定義信號與槽的使用
3.2.1、定義信號
3.2.2、定義槽函數(shù)
3.2.3、連接信號與槽函數(shù)
3.2.4、發(fā)射信號
3.2.5、實例
1、信號與槽的概念
信號(signal)和槽(slot)是Qt的核心機制,也是在PyQt編程中對象之間進行通信的機制。在創(chuàng)建事件循環(huán)之后,通過建立信號和槽的連接就可以實現(xiàn)對象之間的通信。當信號發(fā)射(emit)時,連接的槽函數(shù)將會自動執(zhí)行。
信號(signal)是在特定情況下被發(fā)射(emit)的一種通告。GUI程序設(shè)計的主要內(nèi)容就是對界面上各組件發(fā)射的特定信號進行響應(yīng),只需要知道什么情況下發(fā)射了哪些信號,然后合理地去響應(yīng)和處理這些信號就可以了。
槽(slot)實質(zhì)上是一個函數(shù),可以被直接調(diào)用,是對信號響應(yīng)的函數(shù)。槽函數(shù)與一般的函數(shù)不同的是:槽函數(shù)可以與一個信號關(guān)聯(lián),當信號被發(fā)射時,關(guān)聯(lián)的槽函數(shù)會被自動執(zhí)行。
在Qt編程中,通過Qt信號和槽機制對鼠標或鍵盤在界面上的操作進行響應(yīng)處理。例如,對鼠標單擊按鈕的執(zhí)行處理信號的操作。
PyQt的窗口控件類中有很多內(nèi)置信號,開發(fā)者也可以添加自定義信號。信號與槽具有如下特點:
- 一個信號可以連接多個槽;
- 一個信號可以連接另一個信號;
- 信號參數(shù)可以是任何Python類型;
- 一個槽可以監(jiān)聽多個信號;
- 信號與槽的連接方式可以是同步連接,也可以是異步連接;
- 信號與槽的連接可能會跨線程;
- 信號可能會斷開。
2、信號與槽的基礎(chǔ)函數(shù)
2.1、創(chuàng)建信號函數(shù)
本文僅描述主要的信號函數(shù),具體詳情可參照官方文檔:Support for Signals and Slots — PyQt v5.15 Reference Guide
PyQt的內(nèi)置信號是自動定義的。使用 PyQt5.QtCore.pyqtSignal()函數(shù)可以為QObject創(chuàng)建一個信號,使用pyqtSingnal()函數(shù)可以把信號定義為類的屬性。pyqtSignal()函數(shù)信息如下圖所以:
2.2、連接信號函數(shù)
使用connect()函數(shù)可以把信號綁定到槽函數(shù)上。connect()函數(shù)信息如下圖所示:
2.3、斷開信號函數(shù)
使用disconnect()函數(shù)可以解除信號與槽函數(shù)的綁定。disconnect()函數(shù)信息如下圖所示:
2.4、發(fā)射信號函數(shù)
使用emit()函數(shù)可以發(fā)射信號。emit()函數(shù)信息如下圖所示:
3、信號和槽的使用方法
信號與槽有三種使用方法,第一種是內(nèi)置信號與槽的使用,第二種是自定義信號與槽的使用,第三種是裝飾器的信號與槽的使用。由于第三種方法本質(zhì)上是第一種方法的衍生,因此這里簡要介紹前兩種方法的使用。
Qt Designer中提供了一些最基礎(chǔ)的信號和槽設(shè)置方法,在實際的項目開發(fā)中,信號和槽最佳的使用方式是Qt Designer和編程相結(jié)合,才能提高開發(fā)效率。
3.1、內(nèi)置信號與槽的使用
所謂內(nèi)置信號與槽的使用,是指在發(fā)射信號時,使用窗口控件的函數(shù),而不是自定義的函數(shù)。在信號與槽中,可以通過 QObject.signal.connect將一個QObject的信號連接到另一個QObject的槽函數(shù)。
可以在【編輯->Edit Signal/slot】中進行信號和槽設(shè)置。
進入信號槽編輯模式,可以直接在發(fā)射者(“Button"按鈕)上按住鼠標左鍵不放,拖動到接收者(Form窗體)上,這樣就建立起了連接,如下圖所示:
接著會彈出“配置連接"對話框,如下圖所示:
可以看到按鈕控件會發(fā)射很多內(nèi)置信號和槽,選擇所需信號,然后單擊“OK"按鈕,就會生成對應(yīng)的槽函數(shù)處理。
例如,我想實現(xiàn)單擊按鈕關(guān)閉窗口的效果,所以這里勾選“顯示從QWidget繼承的信號和槽"復(fù)選框。
在左側(cè)按鈕的信號欄里選擇clicked()信號,在右側(cè)的Form槽函數(shù)中選擇close(),這意味著對按鈕單擊會發(fā)射clicked信號,這個信號會被Form窗體的槽函數(shù)close()捕捉到,并觸發(fā)該窗體的close行為(也就是關(guān)閉該窗體)。
連接信號和槽成功后,會發(fā)現(xiàn)在Edit Signal/slot(編輯信號/槽)模式下,所創(chuàng)建的信號和槽關(guān)系的連線是紅色的,如下圖所示:
接著將UI界面轉(zhuǎn)換為Python文件,這里我使用Eric 6編譯,不再贅述,效果如下所示:
拓展學(xué)習(xí):Python Qt GUI設(shè)計:將UI文件轉(zhuǎn)換為Python文件的三種妙招(基礎(chǔ)篇—2)?
UI文件編譯后代碼如下所示:
from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_Form(object):def setupUi(self, Form):Form.setObjectName("Form")Form.resize(383, 276)self.pushButton = QtWidgets.QPushButton(Form)self.pushButton.setGeometry(QtCore.QRect(140, 120, 93, 28))self.pushButton.setObjectName("pushButton")self.retranslateUi(Form)self.pushButton.clicked.connect(Form.close)QtCore.QMetaObject.connectSlotsByName(Form)def retranslateUi(self, Form):_translate = QtCore.QCoreApplication.translateForm.setWindowTitle(_translate("Form", "Form"))self.pushButton.setText(_translate("Form", "Button"))if __name__ == "__main__":import sysapp = QtWidgets.QApplication(sys.argv)Form = QtWidgets.QWidget()ui = Ui_Form()ui.setupUi(Form)Form.show()sys.exit(app.exec_())
代碼中,通過connect函數(shù)連接按鈕的clicked()信號和槽函數(shù)Form.close(),如下所示:
self.pushButton.clicked.connect(Form.close)
運行程序,按鈕是信號發(fā)射者,當單擊按鈕之后會發(fā)射一個信號,通過這行代碼程序內(nèi)部的通信機制知道這個按鈕的單擊事件被連接到窗體的關(guān)閉事件上,然后通知接收者窗體,可以運行槽函數(shù)close(),實現(xiàn)窗口關(guān)閉。
3.2、自定義信號與槽的使用
自定義信號與槽是指在發(fā)射信號時,不使用窗口控件的函數(shù),而是使用自定義的函數(shù)(簡單地說,就是使用pyqtSignal類實例發(fā)射信號)。
之所以要使用自定義信號與槽,是因為通過內(nèi)置函數(shù)發(fā)射信號有自身的缺陷,主要是以下三點:
- 內(nèi)置函數(shù)只包含一些常用的信號,有些信號的發(fā)射找不到對應(yīng)的內(nèi)置函數(shù);
- 內(nèi)置函數(shù)只有在特定情況下(如按鈕的點擊事件)才能發(fā)射這種信號;
- 內(nèi)置函數(shù)傳遞的參數(shù)是特定的,不可以自定義。使用自定義的信號函數(shù)則沒有這些缺陷。
在PyQt5編程中,自定義信號與槽的適用范圍很靈活。例如,因為業(yè)務(wù)需求,在程序中的某個地方需要發(fā)射一個信號,傳遞多種數(shù)據(jù)類型(實際上就是傳遞參數(shù)),然后在槽函數(shù)中接收傳遞過來的數(shù)據(jù),這樣就可以非常靈活地實現(xiàn)一些業(yè)務(wù)邏輯。
自定義信號的一般流程如下:
- 定義信號
- 定義槽函數(shù)
- 連接信號與槽函數(shù)
- 發(fā)射信號
3.2.1、定義信號
使用pyqtSingnal()函數(shù)可以把信號定義為類的屬性,示例代碼如下所示:
#無參數(shù)的信號signal1=pyqtSignal()#帶一個參數(shù)(整數(shù))的信號signal2=pyqtSignal(int)#帶兩個參數(shù)(整數(shù),字符串)的信號signal3=pyqtSignal(int,str)#帶一個參數(shù)(列表)的信號signal4=pyqtSignal(list)#帶一個參數(shù)(字典)的信號signal5=pyqtSignal(dict)#帶(整數(shù) 字符串)或者(字符串)的信號signal6=pyqtSignal([int,str],[str])
3.2.2、定義槽函數(shù)
定義一個槽函數(shù),它有多個不同的輸入?yún)⑤敂?shù),示例代碼如下所示:
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.2.3、連接信號與槽函數(shù)
使用connect()函數(shù)可以把信號綁定到槽函數(shù)上,示例代碼如下所示:
#信號與槽函數(shù)的鏈接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)
3.2.4、發(fā)射信號
使用emit()函數(shù)可以發(fā)射信號,示例代碼如下所示:
#信號發(fā)射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('第六')
3.2.5、實例
將上述片段代碼,整合,非常簡單,各位可以看著理解。
from PyQt5.QtCore import QObject,pyqtSignalclass CusSignal(QObject):#無參數(shù)的信號signal1=pyqtSignal()#帶一個參數(shù)(整數(shù))的信號signal2=pyqtSignal(int)#帶兩個參數(shù)(整數(shù),字符串)的信號signal3=pyqtSignal(int,str)#帶一個參數(shù)(列表)的信號signal4=pyqtSignal(list)#帶一個參數(shù)(字典)的信號signal5=pyqtSignal(dict)#帶(整數(shù) 字符串)或者(字符串)的信號signal6=pyqtSignal([int,str],[str])def __init__(self,parent=None):super(CusSignal, self).__init__(parent)#信號與槽函數(shù)的鏈接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)#信號發(fā)射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('第六')#槽函數(shù)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()
?運行效果如下所示:
關(guān)于信號與槽的使用方法就講到這了,在后面的實踐中我們再細聊,感興趣小伙伴可看看以下的拓展學(xué)習(xí)鏈接~
參考資料、拓展學(xué)習(xí):
《Python QT GUI與數(shù)據(jù)可視化編程》作者:楊海玲責(zé)任編輯 (中國)王維波 栗寶
《PyQt5快速開發(fā)與實戰(zhàn)》王碩
官方網(wǎng)站:PyQt API中信號與槽詳細解釋
Qt for Python 信號和槽的使用詳解
PyQt中的信號(signal)和槽(slot)機制以及Designer中的使用?
Python GUI庫圖形界面開發(fā)之PyQt5信號與槽的高級使用技巧(自定義信號與槽)詳解與實例?
總結(jié)
以上是生活随笔為你收集整理的Python Qt GUI设计:信号与槽的使用方法(基础篇—7)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python Qt GUI设计:如何调整
- 下一篇: 和12岁小同志搞创客开发:如何驱动LED