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())
相关推荐
数字化顾问2 小时前
Python:OpenCV 教程——从传统视觉到深度学习:YOLOv8 与 OpenCV DNN 模块协同实现工业缺陷检测
python
学生信的大叔3 小时前
【Python自动化】Ubuntu24.04配置Selenium并测试
python·selenium·自动化
诗句藏于尽头4 小时前
Django模型与数据库表映射的两种方式
数据库·python·django
智数研析社5 小时前
9120 部 TMDb 高分电影数据集 | 7 列全维度指标 (评分 / 热度 / 剧情)+API 权威源 | 电影趋势分析 / 推荐系统 / NLP 建模用
大数据·人工智能·python·深度学习·数据分析·数据集·数据清洗
扯淡的闲人5 小时前
多语言编码Agent解决方案(5)-IntelliJ插件实现
开发语言·python
moxiaoran57535 小时前
Flask学习笔记(一)
后端·python·flask
秋氘渔5 小时前
迭代器和生成器的区别与联系
python·迭代器·生成器·可迭代对象
Gu_shiwww5 小时前
数据结构8——双向链表
c语言·数据结构·python·链表·小白初步
Dxy12393102167 小时前
python把文件从一个文件复制到另一个文件夹
开发语言·python
sonrisa_8 小时前
collections模块
python