0

所以,我知道我可以毫无问题地做到这一点:

button = widget.libray.Button()

class X():
  @button.on_click
  def click(self, event):
    ...

没有问题。

...但这很烦人,因为现在“按钮”超出了课程范围;我希望这是一个类属性。如何为类成员使用 @blah 装饰语法?

我当然不能使用装饰器,像这样:

class UiDemo(cocos.cocosnode.CocosNode):

  def on_enter(self):
    self.b = Button(text='Hello World')
    self.bt = b.event(self.bt) # <--- !!! Instead of decorator!
    vbox = VBox(elements=[self.b])
    self.dialog = Dialog(title='My Dialog', x=100, y=100, content=vbox, width=200, height=100)
    cocos.director.director.window.push_handlers(self.dialog)

  # @self.b.event doesn't work here, obviously.
  def bt(self, button):
     print('Button pressed: %s' % button)

  def on_exit(self):
    cocos.director.director.window.remove_handlers(self.dialog)

  def draw(self):
    self.dialog.on_draw()

class Client:
  def run(self):
    cocos.director.director.init()
    test = UiDemo()
    main_scene = cocos.scene.Scene(test)
    cocos.director.director.run (main_scene)

我的意思是,我看到了问题;该方法是在定义类时在类上定义的(我猜),所以即使你在init () 步骤中创建了小部件,它在类定义被解析的时候也不存在,所以它可以'当时不能用作装饰者。

我想知道是否有某种解决方法?

当然,在很多情况下,您希望您的装饰器属性引用附加到该类的某物的实例?

(从我上面的例子可以看出,这不仅仅是“假设”的情况;这是本周我第二次使用冗长的 self.func = self.instance.dec(self.func)表格来做到这一点)

有什么建议么?

(......显然,除了使用不这样做的库,因为它很愚蠢;这不是真正的解决方案。:P)

4

2 回答 2

3

您可以将按钮设为类属性:

class X():
  button = widget.libray.Button()

  @button.on_click
  def click(self, event):
    # blah

如果您尝试实例化多个 X 实例,这当然会导致问题(因为它们将共享同一个按钮),但如果您已button全局定义,这已经是一个问题。

不过,您已经准确地诊断出问题:修饰发生在类定义时,但您希望方法与实例相关联。最终,试图用这些技巧来强迫它可能会令人困惑。您正在创建的按钮实例在概念上与 X 的一个实例相关联,而不是与类本身相关联。您可能会合理地创建一个打算多次实例化的 GUI 类(对于某些特定样式的小部件或其他),在这种情况下,您必须放弃这些技巧,因为您确实需要实例你想绑定事件的时间。

如果你真的想要,你可以设计一个更精细的方案来处理这个问题。例如,您可以让这样的装饰器@onclick('button')将名称button作为属性存储在方法对象上。然后,您可以在__init__其中迭代对象的方法并将它们绑定到具有相应名称的 GUI 小部件上的事件的代码。(也就是说,您创建一个按钮并存储它self.button,然后__init__将此属性的名称与传递给装饰器的名称链接起来,并绑定事件。)

然而,只做显而易见的事情可能更简单:不要试图花哨并使用装饰器在类级别处理特定于实例的行为。只需在方法代码中绑定事件,如第二个示例所示。

于 2013-04-07T06:26:56.030 回答
1

在我看来,混乱出现了,因为你想在不需要的时候装饰。你真正需要做的是注册一个回调。除了注册它,装饰回调也没有意义。

只需将按钮作为成员,就像您已经拥有的一样,然后向它注册回调。

def on_enter(self):
    self.b = Button(text='Hello World')
    b.event(self.bt) # register, don't decorate

此外,您不能使用装饰器(除非创建 global Button),因为装饰是在定义类时完成的,并且该Button成员仅在创建对象时才被实例化,因此您不能在那时注册回调观点。

于 2013-04-07T06:03:32.627 回答