在PySide6中,@Slot() 是信号与槽(Signal & Slot)机制的核心装饰器,用于将普通 Python 方法声明为槽函数(Slot)—— 槽函数是专门响应信号(Signal)触发的回调方法,是 PySide6 中组件交互、异步通信的基础。
一、核心作用
- 标记方法为 “可被信号连接” 的槽函数,让信号(如按钮点击 clicked、文本变化 textChanged)触发时能调用该方法。
- 支持指定参数类型(可选但推荐),提升类型安全性,避免信号传参和槽函数接收类型不匹配。
- 兼容 PySide6 的信号槽连接机制(signal.connect(slot)),是声明槽函数的标准方式。
二、基础用法(最常用场景)
1. 无参数槽函数(最简洁)
适用于不需要接收参数的信号(如按钮点击 clicked),直接用 @slot() 装饰空参方法。
from PySide6.QtWidgets import QApplication, QPushButton, QWidget, QVBoxLayout from PySide6.QtCore import Slot # 导入 slot 装饰器 class MyWindow(QWidget): def __init__(self): super().__init__() self.init_ui() # 声明无参数槽函数 @Slot() def on_button_click(self): print("按钮被点击了!") def init_ui(self): self.setLayout(QVBoxLayout()) self.button = QPushButton("点击我") self.layout().addWidget(self.button) # 信号(clicked)连接槽函数(on_button_click) self.button.clicked.connect(self.on_button_click) if __name__ == "__main__": app = QApplication([]) window = MyWindow() window.show() app.exec()2. 带参数的槽函数(指定类型)
如果信号会传递参数(如滑动条 valueChanged 传递当前值、复选框 toggled 传递布尔值),需在 @slot() 中指定参数类型,让槽函数接收对应参数。
from PySide6.QtWidgets import QApplication, QSlider, QLabel, QVBoxLayout, QWidget from PySide6.QtCore import Slot, Qt class MyWindow(QWidget): def __init__(self): super().__init__() self.init_ui() # 声明接收 int 类型参数的槽函数(对应滑动条 valueChanged 信号的参数类型) @Slot(int) def on_slider_value_change(self, value: int): self.label.setText(f"当前值:{value}") def init_ui(self): self.setLayout(QVBoxLayout()) # 滑动条(范围 0-100,值变化时触发 valueChanged 信号,传递 int 类型值) self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, 100) self.label = QLabel("当前值:0") self.layout().addWidget(self.slider) self.layout().addWidget(self.label) # 信号(valueChanged(int))连接槽函数(on_slider_value_change) self.slider.valueChanged.connect(self.on_slider_value_change) if __name__ == "__main__": app = QApplication([]) window = MyWindow() window.show() app.exec()3. 多个参数的槽函数
若信号传递多个参数(如自定义信号),在 @slot() 中按顺序指定所有参数类型即可。
from PySide6.QtCore import QObject, Signal, Slot class MyObject(QObject): # 自定义信号:传递两个参数(str, int) my_signal = Signal(str, int) @Slot(str, int) # 声明接收 str 和 int 两个参数的槽函数 def on_my_signal(self, msg: str, count: int): print(f"收到信号:{msg},计数:{count}") # 测试 obj = MyObject() obj.my_signal.connect(obj.on_my_signal) obj.my_signal.emit("Hello", 5) # 触发信号,输出:收到信号:Hello,计数:5三、关键注意事项
- 必须继承 QObject 或其子类:
槽函数所在的类必须继承 QObject(如 QWidget、QPushButton、自定义 QObject 子类),否则信号槽机制无法生效(PySide6 信号槽依赖 QObject 的元对象系统)。
- 参数类型匹配:
信号传递的参数类型、数量,必须和 @Slot() 声明的类型、数量完全一致,否则连接失败或运行时报错(推荐显式指定类型,而非省略)。
- 省略类型的写法(官方不推荐):
即使信号时带参数的,也可以直接写 @Slot(不带参数),也可以运行,但无法指定参数类型,类型安全性降低。
- 与 @pyqtSlot 的区别:
PyQt5中用 @pyqtSlot,而 PySide6 中统一用 @Slot(从 PySide6.QtCore 导入),两者功能完全一致,只是框架不同的命名差异。
- 槽函数的访问权限:
槽函数可以是 def(实例方法)、@staticmethod(静态方法),但不能是 @classmethod(类方法),且通常用 def 实例方法(可访问组件实例属性)。
- 使用QMetaObject.connectSlotsByName()时,@Slot() 是必要的:
不使用@Slot装饰器:
from PySide6.QtWidgets import QApplication, QPushButton, QWidget, QVBoxLayout from PySide6.QtCore import Slot, QMetaObject # 导入 slot 装饰器 class MyWindow(QWidget): def __init__(self): super().__init__() self.init_ui() QMetaObject.connectSlotsByName(self) def init_ui(self): self.setLayout(QVBoxLayout()) self.button = QPushButton("点击我") self.button.setObjectName("button") self.layout().addWidget(self.button) # @Slot() # 不使用 slot 装饰器声明 def on_button_clicked(self): self.sender().setText("你点击了按钮") if __name__ == "__main__": app = QApplication([]) window = MyWindow() window.show() app.exec()使用@Slot装饰器:
from PySide6.QtWidgets import QApplication, QPushButton, QWidget, QVBoxLayout from PySide6.QtCore import Slot, QMetaObject # 导入 slot 装饰器 class MyWindow(QWidget): def __init__(self): super().__init__() self.init_ui() QMetaObject.connectSlotsByName(self) def init_ui(self): self.setLayout(QVBoxLayout()) self.button = QPushButton("点击我") self.button.setObjectName("button") self.layout().addWidget(self.button) @Slot() # 使用 slot 装饰器声明 def on_button_clicked(self): self.sender().setText("你点击了按钮") if __name__ == "__main__": app = QApplication([]) window = MyWindow() window.show() app.exec()四、常见使用场景
- 组件交互:按钮点击、菜单选择、滑动条拖动、输入框文本变化等(系统内置信号)。
- 自定义通信:自定义信号(Signal)触发时,用槽函数响应(如子组件向父组件传值、线程间通信)。
- 异步回调:结合 QThread 时,子线程通过信号触发主线程的槽函数(避免跨线程操作 UI)。
简单说,PySide6 的 @slot() 就是给方法 “打标签”,告诉 PySide6:“这个方法是用来响应信号的,请允许信号触发它”,是信号槽机制的核心语法。