我正在使用 Qt/PySide 开发一个 GUI,其中包含许多处理各种小部件的单独类。每个小部件管理按钮和其他用户输入之间的信号。我发现自己不得不重用代码在方法函数的开始处阻止小部件信号,然后在结束时释放信号。我决定尝试编写一个通用装饰器来为我做这件事。
我已经搜索了 SO 并尝试在使用装饰器的经验很少的情况下尽我所能实现这一点,所以我对我的解决方案不满意。
我的问题是,编写可以访问和运行该类中遵循清晰格式的方法的通用装饰器的最佳方法是什么?无论如何,我的方法是个好方法吗?
为清楚起见,这是我的代码与重复代码的样子(为简洁起见,我删除了一些):
class WidgetController(...):
def __init__(...):
self.widget.myWidget.currentIndexChanged.connect(reactToChange)
def reactToChange(...):
self.widget.myWidget.blockSignals(True) # Repetetive line...
...
self.widget.myWidget.blockSignals(False)
def anotherFunction(...):
self.widget.anotherWidget.blockSignals(True)
...
self.widget.anotherWidget.blockSignals(False)
我想要以下内容:
class WidgetController(...):
@blockSignals(myWidget)
def reactToChange(...):
...
@blockSignals(anotherWidget, alsoBlockThisWidget)
def anotherFunction(...):
...
我已经开发了一个装饰器(在此处、此处和此处的帮助下),但我不愿展示它,因为它感觉非常笨重。它使用self
我不理解的地方以及exec
嵌套函数,并且需要将小部件名称作为字符串传递,但它似乎确实有效。这里是:
class BlockSignals(object):
def __init__(self, *toBeBlocked):
self.toBeBlocked = toBeBlocked
def __call__(self, f):
toBeBlocked = self.toBeBlocked
def wrapped_f(self, *args):
for b in toBeBlocked:
exec 'self.widget.' + b + '.blockSignals(False)' in locals()
f(self, *args)
for b in toBeBlocked:
exec 'self.widget.' + b + '.blockSignals(False)' in locals()
return wrapped_f
用法:
class WidgetController(...):
@BlockSignals("myWidget")
def reactToChange(...):
...
@BlockSignals("anotherWidget", "alsoBlockThisWidget")
def anotherFunction(...):
如您所见,它并不漂亮。我希望能够摆脱字符串解析,摆脱exec
s,整理出令人困惑self
的 s 并能够通过将实际的小部件对象传递给它来实现它@BlockSignals(self.widget.myWidget)
。不幸的是,我已经达到了我的能力极限,有人可以帮忙吗?