pyqt 信号与槽
PySide6 信号与槽机制详解
引言
PySide6 是 Qt for Python 的官方绑定库,为 Python 提供了强大的 GUI 开发能力。其中,信号与槽(Signals and Slots) 机制是 Qt 事件处理系统的核心,它允许对象之间进行松耦合的通信,极大提高了应用程序的灵活性和可维护性。
本篇文章将详细介绍 PySide6 信号与槽的基本用法,包括如何连接信号、传递参数、自定义信号等。
1. 信号与槽基础
在 PySide6 中,信号(Signal) 用于触发事件,槽(Slot) 是用来处理事件的函数。当信号被触发时,所有连接到该信号的槽都会被调用。
1.1 连接信号与槽
最简单的信号与槽连接方式是使用 connect()
方法。例如,按钮的 clicked
信号可以连接到一个函数:
from PySide6.QtWidgets import QApplication, QPushButton
import sys
def on_button_clicked():
print("按钮被点击!")
app = QApplication(sys.argv)
button = QPushButton("点击我")
button.clicked.connect(on_button_clicked) # 连接信号与槽
button.show()
sys.exit(app.exec())
当用户点击按钮时,on_button_clicked
函数会被调用,终端会输出 "按钮被点击!"
。
2. 传递参数
2.1 使用 lambda
传递参数
有时候,我们希望在槽函数中使用额外的参数,可以使用 lambda
进行包装:
button.clicked.connect(lambda: print("按钮点击,参数:Hello"))
完整示例:
from PySide6.QtWidgets import QApplication, QPushButton
import sys
app = QApplication(sys.argv)
button = QPushButton("点击传参")
button.clicked.connect(lambda: print("按钮点击,参数:Hello"))
button.show()
sys.exit(app.exec())
2.2 使用 functools.partial
传递多个参数
如果 lambda
不够灵活,我们可以使用 functools.partial
传递多个参数:
from PySide6.QtWidgets import QApplication, QPushButton
from functools import partial
import sys
def on_button_clicked(param1, param2):
print(f"按钮点击,参数1: {param1}, 参数2: {param2}")
app = QApplication(sys.argv)
button = QPushButton("点击传递多个参数")
button.clicked.connect(partial(on_button_clicked, "Hello", 42))
button.show()
sys.exit(app.exec())
3. 绑定类方法
在 PySide6 的面向对象开发中,通常会在类中定义槽函数。例如:
from PySide6.QtWidgets import QApplication, QPushButton, QWidget
import sys
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.button = QPushButton("类方法绑定", self)
self.button.clicked.connect(self.on_button_clicked)
self.show()
def on_button_clicked(self):
print("类方法响应点击事件")
app = QApplication(sys.argv)
window = MyApp()
sys.exit(app.exec())
在这个例子中,self.button.clicked.connect(self.on_button_clicked)
绑定了类的方法 on_button_clicked
,当按钮被点击时,该方法会执行。
4. 断开信号连接
有时候,我们可能需要在特定条件下断开信号与槽的连接。可以使用 disconnect()
方法:
from PySide6.QtWidgets import QApplication, QPushButton
import sys
app = QApplication(sys.argv)
button = QPushButton("解绑事件")
def on_click():
print("按钮点击!")
button.clicked.connect(on_click)
button.clicked.disconnect() # 断开信号与槽的连接
button.show()
sys.exit(app.exec())
执行后,即使点击按钮,也不会触发 on_click
。
5. 连接多个槽函数
一个信号可以连接多个槽,所有槽会按照连接顺序依次执行。例如:
from PySide6.QtWidgets import QApplication, QPushButton
import sys
def on_click1():
print("按钮点击 - 处理函数 1")
def on_click2():
print("按钮点击 - 处理函数 2")
app = QApplication(sys.argv)
button = QPushButton("点击触发多个槽函数")
button.clicked.connect(on_click1)
button.clicked.connect(on_click2)
button.show()
sys.exit(app.exec())
点击按钮后,控制台会依次输出:
按钮点击 - 处理函数 1
按钮点击 - 处理函数 2
6. 自定义信号
PySide6 允许用户自定义信号,并在适当的时候触发它们。要定义自定义信号,需要继承 QObject
并使用 Signal
关键字:
from PySide6.QtCore import QObject, Signal
class MySignalEmitter(QObject):
my_signal = Signal(str) # 定义信号,传递字符串参数
def emit_signal(self):
self.my_signal.emit("Hello, PySide6!") # 触发信号
# 定义槽函数
def on_signal_received(message):
print(f"收到信号,消息:{message}")
emitter = MySignalEmitter()
emitter.my_signal.connect(on_signal_received) # 连接信号与槽
emitter.emit_signal() # 触发信号
运行后,控制台会输出:
收到信号,消息:Hello, PySide6!
7. 线程中的信号与槽
在多线程环境下,PySide6 的信号与槽非常有用,可以实现线程间通信。例如,一个后台任务完成后通知主线程:
from PySide6.QtCore import QThread, Signal
import time
class Worker(QThread):
finished = Signal() # 定义信号
def run(self):
time.sleep(3) # 模拟耗时任务
self.finished.emit() # 任务完成,发送信号
def task_completed():
print("后台任务完成!")
worker = Worker()
worker.finished.connect(task_completed) # 连接信号到槽
worker.start() # 启动线程
if __name__ == "__main__":
import sys
from PySide6.QtWidgets import QApplication, QWidget
app = QApplication(sys.argv)
widget = QWidget()
widget.show()
sys.exit(app.exec())
运行后,3 秒后会打印 "后台任务完成!"
。
8. 总结
在 PySide6 中,信号与槽提供了一种灵活的方式来处理事件,使得对象之间的通信变得简单而高效。我们学习了:
- 使用
connect()
绑定信号与槽 - 通过
lambda
和partial
传递参数 - 绑定类方法
- 断开信号连接
- 连接多个槽函数
- 创建自定义信号
- 线程中的信号与槽