pyqtSignal
和 pyqtSlot
教學在使用 PyQt5 開發 GUI 程式時,信號 (Signal) 和 槽 (Slot) 是重要的機制,用於元件之間的通訊。
PyQt 提供了 pyqtSignal
和 pyqtSlot
來自定義信號和槽,進一步實現更靈活的功能。
pyqtSignal
:自定義信號pyqtSignal
是用來定義自訂信號的工具。你可以使用信號來通知其他部分程式某些事件發生了。
from PyQt5.QtCore import QObject, pyqtSignal
class MyObject(QObject):
my_signal = pyqtSignal([參數類型1, 參數類型2, ...])
from PyQt5.QtCore import QObject, pyqtSignal
class Worker(QObject):
# 定義一個信號,攜帶一個字符串參數
progress_signal = pyqtSignal(str)
def do_work(self):
# 當工作進行時,發出信號
for i in range(5):
self.progress_signal.emit(f"Step {i + 1} completed!")
# 創建對象
worker = Worker()
# 定義槽函數
def handle_progress(message):
print(message)
# 將信號連接到槽
worker.progress_signal.connect(handle_progress)
# 開始工作並觸發信號
worker.do_work()
輸出:
Step 1 completed!
Step 2 completed!
Step 3 completed!
Step 4 completed!
Step 5 completed!
pyqtSlot
:明確的槽函數pyqtSlot
是用來定義槽函數的裝飾器。儘管 Python 的普通函數也能作為槽函數,但 pyqtSlot
能帶來一些優勢,例如:
from PyQt5.QtCore import pyqtSlot
@pyqtSlot(參數類型1, 參數類型2, ...)
def your_slot_function(...):
...
pyqtSlot
定義槽from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot
class Worker(QObject):
progress_signal = pyqtSignal(str)
def __init__(self):
super().__init__()
# 將信號連接到槽
self.progress_signal.connect(self.handle_progress)
@pyqtSlot(str) # 使用 pyqtSlot 裝飾器
def handle_progress(self, message):
print(f"Received message: {message}")
def do_work(self):
for i in range(3):
self.progress_signal.emit(f"Task {i + 1} done")
# 測試
worker = Worker()
worker.do_work()
輸出:
Received message: Task 1 done
Received message: Task 2 done
Received message: Task 3 done
以下是一個更複雜的例子,展示信號與槽的結合用法。
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget
class MyWidget(QWidget):
# 自訂信號,帶一個字符串參數
button_clicked_signal = pyqtSignal(str)
def __init__(self):
super().__init__()
self.setWindowTitle("信號與槽範例")
# 設置介面
self.label = QLabel("按下按鈕會觸發信號")
self.button = QPushButton("點我")
layout = QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.button)
self.setLayout(layout)
# 信號連接槽
self.button.clicked.connect(self.emit_signal)
self.button_clicked_signal.connect(self.update_label)
def emit_signal(self):
# 當按鈕被點擊時,發出自訂信號
self.button_clicked_signal.emit("按鈕被按下了!")
@pyqtSlot(str) # 使用 pyqtSlot 定義槽
def update_label(self, message):
self.label.setText(message)
# 測試程式
app = QApplication([])
window = MyWidget()
window.show()
app.exec_()
button_clicked_signal = pyqtSignal(str)
定義了一個帶字符串參數的自訂信號。emit_signal
,發出信號。 @pyqtSlot(str)
定義槽函數 update_label
,更新介面上的標籤文字。pyqtSignal
和 pyqtSlot
必須一起使用嗎?pyqtSlot
能提供更好的效能和類型檢查。pyqtSlot
裝飾槽函數,提升效能。