PySide(PyQt)利用回调和闭包定义信号与槽

如图3个按钮,均设为checkable,放置在一个groupbox内成为一个按钮组,要求实现的功能:当点击某个按钮时将本按钮设为选中(setChecked(True),并取消选中按钮站中的其他所有按钮(setChecked(False))。

首先输入以下代码:

python 复制代码
import sys

from PySide6.QtCore import Signal, QObject
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QGroupBox


class MainWindow(QMainWindow):
    btn_signal = Signal(object)

    def __init__(self):
        super().__init__()

        self.setWindowTitle("Main Window with Buttons")
        self.btn_group = QGroupBox('buttonGroup', self)
        self.btn_group.setGeometry(50, 50, 200, 300)

        # 创建按钮
        self.button1 = QPushButton('Button 1', self.btn_group)
        self.button1.setGeometry(50, 50, 100, 50)
        self.button2 = QPushButton('Button 2', self.btn_group)
        self.button2.setGeometry(50, 120, 100, 50)
        self.button3 = QPushButton('Button 3', self.btn_group)
        self.button3.setGeometry(50, 190, 100, 50)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()

    # 按钮站的定义
    btnStation = window.btn_group.children()
    for b in btnStation:
        b.setCheckable(True)

    # 槽函数
    def slot(btn):
        self = btn
        for b in btnStation:
            b.setChecked(False)
        self.setChecked(True)


    for b in btnStation:
        b.clicked.connect(lambda: slot(b))  # 连接信号到槽函数

    sys.exit(app.exec())

看上去好像没问题,但是运行结果如下:无论点击哪一个按钮,只有按钮3被选中。

问题在于 slot 函数定义, 在 lambda: slot(b) 中,b 是一个循环变量,其值在整个循环执行期间会发生变化。这意味着在每次循环中,b 的值都会被最后一个按钮对象所覆盖,因此当任何按钮被点击时,实际上都会调用 slot(btnStation[-1]),也就是列表中最后一个按钮的状态会始终被设置为选中,而其他按钮则会被取消选中。

使用回调和闭包:

python 复制代码
import sys

from PySide6.QtCore import Signal, QObject
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QGroupBox


class MainWindow(QMainWindow):
    btn_signal = Signal(object)

    def __init__(self):
        super().__init__()

        self.setWindowTitle("Main Window with Buttons")
        self.btn_group = QGroupBox('buttonGroup', self)
        self.btn_group.setGeometry(50, 50, 200, 300)

        # 创建按钮
        self.button1 = QPushButton('Button 1', self.btn_group)
        self.button1.setGeometry(50, 50, 100, 50)
        self.button2 = QPushButton('Button 2', self.btn_group)
        self.button2.setGeometry(50, 120, 100, 50)
        self.button3 = QPushButton('Button 3', self.btn_group)
        self.button3.setGeometry(50, 190, 100, 50)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()

    # 按钮站的定义
    btnStation = window.btn_group.children()
    for b in btnStation:
        b.setCheckable(True)

    # 回调
    def call_slot(btn):
        # 闭包
        def slot():
            self = btn
            for b in btnStation:
                b.setChecked(False)
            self.setChecked(True)

        return slot


    for b in btnStation:
        b.clicked.connect(call_slot(b))  # 连接信号到槽函数

    sys.exit(app.exec())
相关推荐
zone773921 小时前
001:简单 RAG 入门
后端·python·面试
F_Quant1 天前
🚀 Python打包踩坑指南:彻底解决 Nuitka --onefile 配置文件丢失与重启报错问题
python·操作系统
允许部分打工人先富起来1 天前
在node项目中执行python脚本
前端·python·node.js
IVEN_1 天前
Python OpenCV: RGB三色识别的最佳工程实践
python·opencv
haosend1 天前
AI时代,传统网络运维人员的转型指南
python·数据网络·网络自动化
曲幽1 天前
不止于JWT:用FastAPI的Depends实现细粒度权限控制
python·fastapi·web·jwt·rbac·permission·depends·abac
blasit2 天前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
IVEN_2 天前
只会Python皮毛?深入理解这几点,轻松进阶全栈开发
python·全栈
Ray Liang2 天前
用六边形架构与整洁架构对比是伪命题?
java·python·c#·架构设计
AI攻城狮2 天前
如何给 AI Agent 做"断舍离":OpenClaw Session 自动清理实践
python