You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免PyQt按钮clicked信号在装饰器下传递布尔值?

问题描述

我正在使用Qt Designer和PyQt5开发QT项目,其中一个按钮的clicked信号会传递布尔值。绑定信号与函数的代码如下(装饰器位于类内部,且无论使用何种装饰器,clicked信号都会传入布尔参数):

class Demo:
    def __init__(self):
        # bind the signal and function
        ...
        self.ui.pushButton_disconnect.clicked.connect(
            self.robot.disconnect_devices
        )
        ...
    def my_decorator(func):
        def wrapper(self,*args,**kwargs):
            '''
            args and kwargs is necessary 
            because other decorated functions have parameters
            '''
            # do something
            return func(self,*args,**kwargs)
        return wrapper
    # function
    @my_decorator
    def disconnect_devices(self, *args):
        print(args)
        # do something

目前我必须使用*args来接收传入的False,我知道可以在connect中使用lambda来规避此问题。我发现原因是装饰器中使用了*args,导致clicked信号自动传入参数,因此函数必须用*args接收。请问有没有其他解决方法?或者能否将clicked信号设置为无参数信号?

解决方案

方法1:让装饰器自动适配函数参数

利用inspect模块获取目标函数的签名,只传递它能接收的参数,既保留装饰器对带参函数的兼容性,又能让无参函数自动忽略多余参数:

import inspect

class Demo:
    def __init__(self):
        # ... 原有初始化代码 ...

    def my_decorator(func):
        def wrapper(self, *args, **kwargs):
            # 获取函数签名,排除第一个self参数
            sig = inspect.signature(func)
            param_names = list(sig.parameters.keys())[1:]
            # 筛选出函数能接收的位置参数和关键字参数
            valid_args = args[:len(param_names)]
            valid_kwargs = {k: v for k, v in kwargs.items() if k in param_names}
            
            # 执行装饰逻辑
            # do something
            
            return func(self, *valid_args, **valid_kwargs)
        return wrapper

    @my_decorator
    def disconnect_devices(self):  # 无需*args,直接定义无参函数
        # 执行设备断开逻辑
        pass

方法2:显式使用无参数的clicked信号重载

QPushButton的clicked信号有两个重载版本,指定使用无参数的那个版本,信号触发时就不会传递布尔值:

# 连接信号时指定无参数重载
self.ui.pushButton_disconnect.clicked[()].connect(
    self.robot.disconnect_devices
)

之后disconnect_devices就能直接定义为无参数函数,装饰器的*args不会收到多余参数。

方法3:在装饰器中针对性忽略布尔参数

如果只需要处理clicked信号的布尔参数,可以在装饰器里判断并忽略这类参数,适合特定场景的快速优化:

class Demo:
    def my_decorator(func):
        def wrapper(self, *args, **kwargs):
            # 检查是否是单个布尔参数(clicked信号默认传入的类型)
            if len(args) == 1 and isinstance(args[0], bool):
                # 忽略该参数,直接调用原函数
                return func(self)
            # 其他情况正常传递参数
            return func(self, *args, **kwargs)
        return wrapper

    @my_decorator
    def disconnect_devices(self):
        # 执行设备断开逻辑
        pass

内容的提问来源于stack exchange,提问作者肉蛋充肌

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 19:37:51