所有的GUI應用程序都是基于事件驅動的。事件主要由應用程序的用戶產生,但也可以由其他方式生成。
比如,網絡連接,定時器。為了對事件作出響應,系統會產生一個特定的信號。這個信號可視為PyQt庫中系統事件的代表。
要處理信號,需將一個類的函數或方法(PyQt中稱之為"slot")與之相關聯。當事件觸發時,該函數或方法被調用,成為信號 的處理程序。
使用繼承自QObject類的connect()方法來指定信號的處理程序。調用格式為:
connect(slot[, type=PyQt5.QtCore.Qt.AutoConnection[, no_receiver_check=False]])
參數:
slot – 可調用的函數或另一個信號
type – 要連接的類型。程序應用到多線程編程時,要特別注意這個參數。type的可選值有:
AutoConnection,0:默認值。
如果信號和處理程序在同一線程,等同于DirectConnection;如果不在同一線程,則等同于QueedConnection。
DirectConnection, 1:
信號觸發后,處理程序立即在源數據流(source stream)中執行。
QueuedConnection, 2:
信號觸發后進行處理隊列,處理程序在信號接收方執行。
BlockingQueuedConnection, 4:
類似于QueuedConnection,但在處理程序執行時,線程處于阻塞狀態 。需要注意的是信號和處理程序必須在不同線程。UniqueConnection,0x80:表明處理程序只能指定一次。該值可以和前面的值進行組合應用。
no_receiver_check – suppress the check that the underlying C++ receiver instance still exists and deliver the signal anyway.(禁止檢查底層C ++接收器實例是否仍然存在,并傳遞信號。)
例1:
將on_clicked_button ()函數作為button按鈕clicked信號處理程序的代碼:
button.clicked.connect(on_clicked_button)
信號可以有不同數量的參數,參數可以為任何類型。在一個類中,可以存在信號名相同,但參數不同的多個信號。這時的調用方式為在信號之后加方括號([ ]) ,方括號內為接收到的數據類型。可以采用類型符號或該類型的英文字符串。
button.clicked[bool].connect(on_clicked_button)
button.clicked["bool].connect(on_clicked_button)
可以給一個信號指定多個處理程序。見下例:
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets
import sys
def on_clicked():
print("按鈕按下: on_clicked ()被調用")
class MyClass():
def __init__(self, x=0):
self.x = x
def __call__(self):
print("按鈕按下: MyClass .__ call __ ()")
print("x =", self.x)
def on_clicked(self):
print("按鈕按下: MyClass.on_clicked ()")
obj = MyClass()
app = QtWidgets.QApplication(sys.argv)
button = QtWidgets.QPushButton("點擊鼠標")
# 指定處理程序
button.clicked.connect(on_clicked)
# 指定處理程序為類的方法
button.clicked.connect(obj.on_clicked)
# 指定處理程序為類實例
button.clicked.connect(MyClass(10))
# 指定處理程序為匿名函數
button.clicked.connect(lambda: MyClass(5)())
button.show()
sys.exit(app.exec_())
程序的輸出為:
按鈕按下: on_clicked ()被調用
按鈕按下: MyClass.on_clicked ()
按鈕按下: MyClass .__ call __ ()
x = 10
按鈕按下: MyClass .__ call __ ()
x = 5
PyQt5中有很多函數可作為信號的處理程序,這些函數稱之為slot。
只要在函數定義前加上裝飾符@pyqtSlot,任何自定義函數都可變為slot。格式為:
@pyqtSlot(types[, name[, result]])
types – the types that define the C++ signature of the slot. Each type may be a Python type object or a string that is the name of a C++ type(定義slot的C++簽名。類型可以是Python的類型也可以是C_++類型的英文字符串).
name – the name of the slot that will be seen by C++. If omitted the name of the Python method being decorated will be used.(C++中可見的slot名稱. 如果省略,將使用被裝飾的函數名. )
result – the type of the result and may be a Python type object or a string that specifies a C++ type. (函數結果的類型。可以是Python的類型也可以是C_++類型的英文字符串)
例2:
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtWidgets
import sys
class MyClass(QtCore.QObject):
def __init__(self):
QtCore.QObject.__init__(self)
@QtCore.pyqtSlot()
def on_clicked(self):
print("按鈕按下. slot on_clicked()")
@QtCore.pyqtSlot(bool, name="myslot")
def on_clicked2(self, status):
print("按鈕按下. slot myslot(bool)", status)
obj = MyClass()
app = QtWidgets.QApplication(sys.argv)
button = QtWidgets.QPushButton("點擊鼠標")
button.clicked.connect(obj.on_clicked)
button.clicked.connect(obj.myslot)
button.show()
sys.exit(app.exec_())
程序輸出:
按鈕按下. slot on_clicked()
按鈕按下. slot myslot(bool) False
PyQt中沒有強制將信號的處理函數轉化成slot,但推薦這樣做,因為調用slot的速度快。