gpt4 book ai didi

python - 使用 Kivy 为同一事件添加多个处理程序的最佳/正确方法是什么?

转载 作者:太空宇宙 更新时间:2023-11-03 13:59:45 26 4
gpt4 key购买 nike

我最近发现了 Kivy-Framework,目前正在使用 PongGame-Example 。我实现了一些函数,通过为 paddle 类提供一些可以绑定(bind)到键盘事件的处理程序,可以使用键盘控制 paddle。不幸的是,我对 kivy 的事件绑定(bind)有点挣扎。

首先我在 PongGame 类中尝试了以下操作

self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
self._keyboard.bind(on_key_down=self.player1.on_keyboard_down)
self._keyboard.bind(on_key_up=self.player1.on_keyboard_up)
self._keyboard.bind(on_key_down=self.player2.on_keyboard_down)
self._keyboard.bind(on_key_up=self.player2.on_keyboard_up)

在 c# 和 WPF 中,我习惯于能够将多个处理程序绑定(bind)到同一个事件,我想我在 Kivy 的文档中看到了类似的内容。不幸的是,在 Kivy 中,这似乎会导致先前添加的绑定(bind)被后来添加的绑定(bind)覆盖,从而导致只有第二个桨能够移动。在文档中,我发现 kivy 多次阻止将函数添加为处理程序,因此我尝试使用 fbind ,因为文档说

As opposed to bind(), it does not check that this function and largs/kwargs has not been bound before to this name. So binding the same callback multiple times will just keep adding it.

我认为这两种方法在某种程度上被视为相同的功能。不幸的是结果是一样的。

所以我所做的是创建额外的方法来将处理程序分组在一起并绑定(bind)它们。

def __init__(self, **kwargs):
super(PongGame, self).__init__(**kwargs)
self.player1.set_input_keys('w', 's')
self.player2.set_input_keys('up', 'down')
self._keyboard = Window.request_keyboard(self._keyboard_closed, self)

self._keyboard.bind(on_key_down=self._on_key_down)
self._keyboard.bind(on_key_up=self._on_key_up)

def _keyboard_closed(self):
self._keyboard.bind(on_key_down=self._on_key_down)
self._keyboard.bind(on_key_up=self._on_key_up)
self._keyboard = None

def _on_key_down(self, keyboard, keycode, text, modifiers):
self.player2.on_keyboard_down(keyboard, keycode, text, modifiers)
self.player1.on_keyboard_down(keyboard, keycode, text, modifiers)

def _on_key_up(self, keyboard, keycode):
self.player1.on_keyboard_up(keyboard, keycode)
self.player2.on_keyboard_up(keyboard, keycode)

不幸的是,这有一个缺点,即我无法解除单个处理程序的绑定(bind)。例如,从两名玩家切换为一名玩家时。

我是 kivy 的新手,不知怎的,我有一种本末倒置的感觉。

处理这个问题的正确或奇怪的方法是什么?

完整代码在这里https://pastebin.com/uq9pxHcFkv 文件与 tutorial (you may have to scroll down a bit) 中的示例完全相同除了我使用了#:kivy 1.10.0

最佳答案

<强>1。正确的方法

您可以在_on_keyboard_down方法中处理键码。

class PongGame(Widget):
ball = ObjectProperty(None)
player1 = ObjectProperty(None)
player2 = ObjectProperty(None)

PLAYER1_UP = 'w'
PLAYER1_DOWN = 's'
PLAYER2_UP = 'up'
PLAYER2_DOWN = 'down'
SENSITIVITY = 10

def __init__(self, **kwargs):
super(PongGame, self).__init__(**kwargs)
self._keyboard = Window.request_keyboard(
self._keyboard_closed, self, 'text')
self._keyboard.bind(on_key_down=self._on_keyboard_down)

def _keyboard_closed(self):
self._keyboard.unbind(on_key_down=self._on_keyboard_down)
self._keyboard = None

def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
if keycode[1] == self.PLAYER1_UP:
self.move_player(self.player1, self.SENSITIVITY)
elif keycode[1] == self.PLAYER1_DOWN:
self.move_player(self.player1, -self.SENSITIVITY)
if keycode[1] == self.PLAYER2_UP:
self.move_player(self.player2, self.SENSITIVITY)
elif keycode[1] == self.PLAYER2_DOWN:
self.move_player(self.player2, -self.SENSITIVITY)
return True

def move_player(self, player, displacement):
player.center_y += displacement

# serve_ball and update methods, ref tutorial
# ...

注释

  • 为了能够仅用一组键来演奏双方,我们打破了 if-elif 链。
  • 使用_keyboard_close取消绑定(bind)处理程序,请引用 docs 中的示例.

<强>2。处理程序处理

你对那辆购物车的看法是对的,你把它弄反了。来自 Event Dispatcher :

If a callback has already been bound to a given event or property, it won’t be added again.

表示使用常规绑定(bind)无法将相同处理程序多次添加到同一事件。您真正想要的是为同一事件调用不同方法。幸运的是,这很容易......

def __init__(self, **kwargs):
super(PongGame, self).__init__(**kwargs)
self._keyboard = Window.request_keyboard(
self._keyboard_closed, self, 'text')
self._keyboard.bind(on_key_down=self._on_keyboard_down1)
self._keyboard.bind(on_key_down=self._on_keyboard_down2)

def _keyboard_closed(self):
self._keyboard.unbind(on_key_down=self._on_keyboard_down1)
self._keyboard.unbind(on_key_down=self._on_keyboard_down2)
self._keyboard = None

def _on_keyboard_down1(self, keyboard, keycode, text, modifiers):
if keycode[1] == self.PLAYER1_UP:
self.move_player(self.player1, self.SENSITIVITY)
elif keycode[1] == self.PLAYER1_DOWN:
self.move_player(self.player1, -self.SENSITIVITY)
return True

def _on_keyboard_down2(self, keyboard, keycode, text, modifiers):
if keycode[1] == self.PLAYER2_UP:
self.move_player(self.player2, self.SENSITIVITY)
elif keycode[1] == self.PLAYER2_DOWN:
self.move_player(self.player2, -self.SENSITIVITY)
return False

有一个问题,最后添加的处理程序应该返回False,否则它将将该事件标记为已处理,并且第一个处理程序将永远不会被调用。

为了更深入地理解,我建议再看一下 kivy properties :

The reason that both functions are called is simple. Binding doesn’t mean overriding. Having both of these functions is redundant and you should generally only use one of the methods of listening/reacting to property changes.

关于python - 使用 Kivy 为同一事件添加多个处理程序的最佳/正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49334697/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com