Ответ 1
Здесь вы просите о двух разных вещах.
- Вы хотите иметь простой объект python,
self.name
подписаться на изменения вQLineEdit
. - Вы хотите, чтобы ваш
QLineEdit
подписался на изменения на простой объект pythonself.name
.
Подписывание изменений на QLineEdit
легко, потому что это то, что для системы сигналов/слотов Qt. Вы просто делаете это
def __init__(self):
...
myQLineEdit.textChanged.connect(self.setName)
...
def setName(self, name):
self.name = name
Более сложная часть - это изменение текста в QLineEdit при изменении self.name
. Это сложно, потому что self.name
- просто простой объект python. Он ничего не знает о сигналах/слотах, и у python нет встроенной системы для наблюдения за изменениями на объектах так, как это делает С#. Вы все равно можете делать то, что хотите.
Используйте функцию getter/setter с функцией свойства Python
Проще всего сделать self.name
a 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
Вы можете просто добавить строку для обновления QLineEdit
в методе setter. Таким образом, всякий раз, когда что-либо изменяет значение x
, будет обновляться QLineEdit
. Например
@name.setter
def name(self, value):
self.myQLineEdit.setText(value)
self._name = value
Обратите внимание, что данные имени фактически хранятся в атрибуте _name
, потому что он должен отличаться от имени получателя/сеттера.
Использовать реальную систему обратного вызова
Слабость всего этого заключается в том, что вы не можете легко изменить этот шаблон наблюдателя во время выполнения. Для этого вам нужно что-то действительно похожее на то, что предлагает С#. Две системы наблюдения стиля С# в python obsub и мой собственный проект observed. Я использую наблюдаемые в своих проектах pyqt с большим успехом. Обратите внимание, что версия наблюдаемого на PyPI находится за версией на 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 = {} #Method name -> 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
, вы можете добавить обратные вызовы к любому методу, который вы хотите во время выполнения. Вот простой пример:
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
и подписаться на него.