您在这里要求两件不同的事情。
- 您希望一个普通的Python对象
self.name
订阅一个 QLineEdit
上的更改。
- 您希望您的
QLineEdit
订阅普通Python对象 self.name
上的更改。
订阅 QLineEdit
的更改很容易,因为这就是Qt信号/槽系统的作用。您只需像这样做:
def __init__(self):
...
myQLineEdit.textChanged.connect(self.setName)
...
def setName(self, name):
self.name = name
更棘手的部分是当self.name
发生变化时,如何让QLineEdit中的文本发生变化。这很困难,因为self.name
只是一个纯Python对象。它不知道任何关于信号/槽的事情,并且Python没有内置的系统来观察对象上的更改,就像C#那样。不过,您仍然可以做到想要的效果。
使用Python的属性功能设置getter/setter
最简单的方法是将self.name
设置为Property。下面是从链接文档中的简短示例(经过修改以增加清晰度):
class Foo(object):
@property
def x(self):
"""This method runs whenever you try to access self.x"""
print("Getting self.x")
return self._x
@x.setter
def x(self, value):
"""This method runs whenever you try to set self.x"""
print("Setting self.x to %s"%(value,))
self._x = value
你可以在setter方法中添加一行代码来更新QLineEdit
。这样,无论什么修改了x
的值,QLineEdit
都会得到更新。例如:
@name.setter
def name(self, value):
self.myQLineEdit.setText(value)
self._name = value
请注意,数据名称实际上保存在名为_name
的属性中,因为它必须与getter/setter的名称不同。
使用真正的回调系统
所有这些的弱点是您无法在运行时轻松更改此观察者模式。要做到这一点,您需要像C#所提供的那样。Python中两个类似于C#风格的观察者系统是obsub和我自己的项目observed。我在自己的PyQt项目中成功地使用了observed。
请注意,PyPI上的observed版本落后于github上的版本。我建议使用github版本。
创建自己的简单回调系统
如果您想以最简单的方式自己处理,可以尝试以下内容:
import functools
def event(func):
"""Makes a method notify registered observers"""
def modified(obj, *arg, **kw):
func(obj, *arg, **kw)
obj._Observed__fireCallbacks(func.__name__, *arg, **kw)
functools.update_wrapper(modified, func)
return modified
class Observed(object):
"""Subclass me to respond to event decorated methods"""
def __init__(self):
self.__observers = {}
def addObserver(self, methodName, observer):
s = self.__observers.setdefault(methodName, set())
s.add(observer)
def __fireCallbacks(self, methodName, *arg, **kw):
if methodName in self.__observers:
for o in self.__observers[methodName]:
o(*arg, **kw)
现在,如果您只是子类化Observed
,那么您可以在运行时向任何方法添加回调。这是一个简单的示例:
现在,如果你只是子类化Observed
,你就可以在运行时为任何想要的方法添加回调函数。这里有一个简单的例子:
class Foo(Observed):
def __init__(self):
Observed.__init__(self)
@event
def somethingHappened(self, data):
print("Something happened with %s"%(data,))
def myCallback(data):
print("callback fired with %s"%(data,))
f = Foo()
f.addObserver('somethingHappened', myCallback)
f.somethingHappened('Hello, World')
>>> Something happened with Hello, World
>>> callback fired with Hello, World
如果您按照上述方式实现了.name
属性,您可以使用@event
装饰setter并订阅它。
observed
版本比github上的版本稍旧。如果您的工作流允许,我建议使用github版本。我一直拖延更新PyPI,因为我需要稍微修改一下文档。如果有足够多的人催促我... - DanielSank