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())
相关推荐
Cooper2544 分钟前
DDC 命令成功但屏幕不动:用 gamma 表重做亮度映射
python·mac
师夷长技以自愈1 小时前
手搓 AI Agent 第 7 篇:菜做砸了别硬炒——错误分类 + 双账本熔断
人工智能·python
用户956256254291 小时前
15 分钟社媒简报 Agent:我只用了搜索和模型两步
python·api
Dumbness1 小时前
关键词回复里写了 {订单号},群机器人整条消息都炸了
python·微信
调接口的阿光1 小时前
调用对话接口时输出被截断怎么办:先看 finish_reason,再决定是续写一次、缩小范围,还是换成更短的格式(Python)
人工智能·python
Cooper252 小时前
单文件 Flask 跑通微信服务器校验:先跑通再谈工程化
python·flask
Cooper252 小时前
三源热榜去重加 AI 摘要:URL 唯一键踩出的三个坑
前端·python
用户4019925568612 小时前
多源异构 B2B 公开需求信号去重与企业实体证据链存储设计(64-bit SimHash 分桶 + Jaccard)
python
aifannihao2 小时前
GitHub Actions 锁文件实测:6 个 uses 只锁住 2 个
python·ci/cd·标准库·供应链安全·github actions
2601_967980112 小时前
使用gensim处理文本(1)语料库与词向量空间
python·自然语言处理·gensim·词向量·文本分析