目前我正在使用PyQT,到目前为止我非常喜欢。但是,我需要双向绑定,并且从互联网上可以找到的稀疏信息中,这是实现它的方法。创建一个PyQTProperty,附加一个getter,一个setter和一个信号(每当值发生变化时都必须调用它以通知GUI)。
from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject
class Test(QObject):
signal = pyqtSignal()
def getName(self):
print("name gotten")
return self._name
def setName(self, name):
print("name changed to " + name)
self.signal.emit()
self._name = name
name = pyqtProperty('QString', fget= getName, fset= setName, notify= signal)
def __init__(self, parent=None):
super().__init__(parent)
# Initialise the value of the properties.
self._name = 'asdf'
这可以按预期工作。但是,我不确定我是否确实正确使用它,但这看起来对我来说非常可怕。事实上,它闻起来很糟糕,我倾向于打开一扇窗户。我现在不得不简单地声明一个属性,而是创建一个setter和一个getter(在声明之前,即在源文件的中途会有声明)和每个属性的信号。这导致了许多重复的代码和不可读的源文件。
将此更改为一行或两行的最佳方法是什么?例如,通过自动代码生成,元编程或宏(我已经查看了MacroPy,但不确定这是否可行)。所以像这样:
name = # magic Python voodoo, automatically handling setters, getters and the signal
提前致谢,如果我需要提供更多信息,请告诉我。
编辑:感谢BrenBarn,我注意到我忘了提到这个代码是如何被实际调用的。 GUI以QML(Qt标记语言)实现,并且通过注册它(如here,qmlRegisterType)使QML知道该对象,之后QML可以实例化并操纵它的实例。为了简洁,我决定不包括完整的源代码示例,因为我主要关注处理getter / setter和信号实例化的更好方法,而不关注QML。
答案 0 :(得分:2)
您可以使用documentation中提到的pyqtProperty()装饰器。它至少删除了单独的定义。
signal = pyqtSignal
@name.setter
def name(self, name):
self._name = name
self.signal.emit()
@pyqtProperty('QString', notifiy=signal)
def name(self):
return self._name