PyQt 中 pyqtSignal 的使用基礎與實例解析

Back
Category : News

喺 PyQt5 入面,pyqtSignal 係一個好重要嘅工具,用來幫程式實現物件之間嘅通訊同事件處理。佢允許開發者自定義信號(Signal),同槽函數(Slot)連繫起來,實現非同步嘅資料傳遞同事件響應。呢篇新聞會詳細講解 pyqtSignal 嘅基本使用方法、定義方式同實際應用場景,仲會提供一個簡單嘅實例,幫你明白點樣喺 PyQt 應用程式入面用佢。

首先,pyqtSignal 必須定義喺一個繼承自 QObject 嘅類別入面,因為信號同槽嘅機制係建基於 Qt 嘅物件模型。喺定義信號嗰陣,佢要作為類別嘅屬性(Class Attribute),而唔係實例變數。簡單嚟講,就係唔可以喺 __init__ 方法入面動態新增信號,否則會報錯,提示 AttributeError: 'PyQt5.QtCore.pyqtSignal' object has no attribute 'connect'。例如,你可以咁定義一個無參數嘅信號:my_signal = pyqtSignal(),或者一個帶參數嘅信號:my_signal = pyqtSignal(str)。呢啲信號可以用 .emit() 方法去觸發,並將參數傳遞畀連繫嘅槽函數。

講到實際應用,pyqtSignal 特別適合用喺多線程程式設計同多頁面通訊嘅場景。例如,喺一個圖片處理工具入面,你可能需要喺後台線程處理圖片數據,然後通過信號將處理結果傳送返主線程,更新用戶界面(UI)。假設你有一個 Worker 類別,負責喺後台處理一張圖片,佢可以定義一個信號 image_processed = pyqtSignal(object),用來傳遞處理完嘅圖片數據。喺主線程入面,你可以將呢個信號連繫到一個槽函數,例如 update_image,用來喺界面上顯示圖片。咁樣,後台同前台嘅通訊就變得安全又高效。

以下係一個簡單嘅程式碼實例,展示點樣用 pyqtSignal 實現信號同槽嘅連繫:
from PyQt5.QtCore import QObject, pyqtSignal
class SignalEmitter(QObject):
my_signal = pyqtSignal(str)
def emit_signal(self):
self.my_signal.emit("Hello, PyQt!")
class SignalReceiver(QObject):
def on_signal_received(self, message):
print(f"Received: {message}")
if __name__ == "__main__":
emitter = SignalEmitter()
receiver = SignalReceiver()
emitter.my_signal.connect(receiver.on_signal_received)
emitter.emit_signal()

喺呢個例子入面,SignalEmitter 定義咗一個帶字符串參數嘅信號,通過 .emit() 發送訊息,然後由 SignalReceiver 嘅槽函數接收並打印出來。執行呢段程式碼,會喺控制台輸出 Received: Hello, PyQt!

除咗基本嘅字符串同數字類型,pyqtSignal 仲支援傳遞複雜數據類型,例如 listdict 同自定義物件。如果你想傳遞一個 NumPy 陣列或者 Pandas DataFrame,建議用 pyqtSignal(object),因為 object 類型可以接受幾乎任何 Python 物件。需要注意嘅係,喺多線程環境下,信號嘅發送同接收必須確保線程安全,否則可能會導致程式崩潰。為咗避免呢啲問題,PyQt 提供咗 QThreadmoveToThread 方法,幫你將物件移到指定線程,確保信號喺正確嘅線程入面處理。

另外,pyqtSignal 支援多重載(Overloaded)信號,允許同一個信號定義多個版本。例如:my_signal = pyqtSignal([int, str], [str]),表示呢個信號可以傳遞 (int, str) 或者單獨嘅 str。喺連繫槽函數嗰陣,你需要明確指定版本,例如 my_signal[str].connect(slot_function)。呢個功能喺複雜嘅應用場景好有用,例如喺一個模擬打印界面入面,根據唔同嘅用戶輸入發送唔同類型嘅信號。

總括嚟講,pyqtSignal 係 PyQt5 入面一個強大嘅工具,幫開發者實現靈活嘅事件驅動程式設計。無論係簡單嘅按鈕點擊,定係複雜嘅多線程數據傳遞,佢都可以提供可靠嘅解決方案。只要跟隨正確嘅定義同使用方法,開發者就能輕鬆構建高效嘅 PyQt 應用程式。想了解更多詳情,可以參考 呢篇博客