PyQt5編程(11):信號與事件的處理—指定信號處理程序

所有的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的速度快。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容