什麼是信號槽?
信號(singal)與槽(slot)用於對象相互通信,信號:當某個對象的某個事件發生時,觸發一個信號,槽:響應指定信號的所做的反應,其實信號槽類似於.NET裏面的委託、事件,比如Repeater控件類,當行數據綁定後,觸發一個ItemDataBound事件,不管使用者使用會監聽該事件並做額外處理,其控件類內部都會觸發該事件,這種機制很多程度提高了類的封裝性和完整性。
PyQt的窗體控件類已經有很多的內置信號,開發者也可以添加自己的自定義信號,信號槽有如下特點:
- 一個信號可以連接到許多插槽。
- 一個信號也可以連接到另一個信號。
- 信號參數可以是任何Python類型。
- 一個插槽可以連接到許多信號。
- 連接可能會直接(即同步)或排隊(即異步)。
- 連接可能會跨線程。
- 信號可能會斷開
內置信號槽、自定義信號槽的使用:
槽的參數個數可以小於等於信號的參數個數,所以這裏按鈕btn的內置信號clicked雖然有一個參數,但是sinTest槽參數可以爲空。
# -*- coding: utf-8 -*-
from PyQt4.QtGui import *
from PyQt4.QtCore import *
def sinTest():
btn.setText("按鈕文本改變")
app = QApplication([])
main = QWidget()
main.resize(200,100)
btn = QPushButton("按鈕文本",main)
##按鈕btn的內置信號連接名爲sinTest的槽
btn.clicked.connect(sinTest)
main.show()
app.exec_()
- 自定義信號槽的使用
# -*- coding: utf-8 -*-
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class SinClass(QObject):
##定義一個無參數的信號
sin1 = pyqtSignal()
##聲明帶一個int類型參數的信號
sin2 = pyqtSignal(int)
##聲明帶一個int和str類型參數的信號
sin3 = pyqtSignal(int,str)
##聲明帶一個列表類型參數的信號
sin4 = pyqtSignal(list)
##聲明帶一個字典類型參數的信號
sin5 = pyqtSignal(dict)
##聲明一個多重載版本的信號,包括了一個帶int和str類型參數的信號,以及帶str參數的信號
sin6 = pyqtSignal([int,str], [str])
def __init__(self,parent=None):
super(SinClass,self).__init__(parent)
##信號連接到指定槽
self.sin1.connect(self.sin1Call)
self.sin2.connect(self.sin2Call)
self.sin3.connect(self.sin3Call)
self.sin4.connect(self.sin4Call)
self.sin5.connect(self.sin5Call)
self.sin6[int,str].connect(self.sin6Call)
self.sin6[str].connect(self.sin6OverLoad)
##信號發射
self.sin1.emit()
self.sin2.emit(1)
self.sin3.emit(1,"text")
self.sin4.emit([1,2,3,4])
self.sin5.emit({"name":"codeio","age":"25"})
self.sin6[int,str].emit(1,"text")
self.sin6[str].emit("text")
def sin1Call(self):
print("sin1 emit")
def sin2Call(self,val):
print("sin2 emit,value:",val)
def sin3Call(self,val,text):
print("sin3 emit,value:",val,text)
def sin4Call(self,val):
print("sin4 emit,value:",val)
def sin5Call(self,val):
print("sin5 emit,value:",val)
def sin6Call(self,val,text):
print("sin6 emit,value:",val,text)
def sin6OverLoad(self,val):
print("sin6 overload emit,value:",val)
sin = SinClass()
signal只能在QObject的子類中定義。如果在子類外直接定義,會出現 AttributeError: 'PyQt4.QtCore.pyqtSignal' object has no attribute 'emit'