让我们从基本的例子开始:
class OuterWidget(Widget):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
print('on_touch_down', self)
return True # doesn't dispatch to InnerWidget
return super().on_touch_down(touch)
class InnerWidget(Widget):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
print('on_touch_down', self)
return super().on_touch_down(touch)
事件首先调度到OuterWidget
,如果它调用super().on_touch_down(touch)
事件调度到子窗口小部件,则事件不会在下一次调度。那很清楚。
我想创建一些与on_touch_down
一起发生的行为并采取相同的行为。试试吧:
class TestBehavior(Widget):
def __init__(self, **kwargs):
self.register_event_type('on_test_event')
super().__init__(**kwargs)
def on_test_event(self, touch):
pass
def on_touch_down(self, touch):
self.dispatch('on_test_event', touch) # Some event that happens with on_touch_down
return super().on_touch_down(touch)
class OuterWidget(TestBehavior, Widget):
def on_test_event(self, touch):
if self.collide_point(*touch.pos):
print('on_test_event', self)
return True # doesn't affect anything, both widgets would recieve on_test_event
return super().on_test_event(touch)
class InnerWidget(TestBehavior, Widget):
def on_test_event(self, touch):
if self.collide_point(*touch.pos):
print('on_test_event', self)
return True
return super().on_test_event(touch)
on_test_event
冒泡不会像on_touch_down
一样工作。无论OuterWidget
返回什么,都会将事件发送到InnerWidget
。之所以会发生这种情况,是因为这两个小部件都会收到触发on_touch_down
的{{1}}事件。
如果我使用on_test_event
在行为中派遣某个事件,这个事件将始终分派给所有孩子,无论他们返回什么内容。但是如果某个小部件没有调用on_touch_down
,我希望不要发送on_test_event
。
我该怎么办?有什么想法吗?
答案 0 :(得分:2)
Widget类处理其所有子节点的事件,如下所示:
(从widget.py复制)
def on_touch_down(self, touch):
'''Receive a touch down event.
:Parameters:
`touch`: :class:`~kivy.input.motionevent.MotionEvent` class
Touch received. The touch is in parent coordinates. See
:mod:`~kivy.uix.relativelayout` for a discussion on
coordinate systems.
:Returns: bool
If True, the dispatching of the touch event will stop.
If False, the event will continue to be dispatched to the rest
of the widget tree.
'''
if self.disabled and self.collide_point(*touch.pos):
return True
for child in self.children[:]:
if child.dispatch('on_touch_down', touch):
return True
正如你所看到的,它会迭代它的childern并发送事件直到 True 被返回。
要创建类似的行为,您可以创建自己的混合类,并使其所有类固有或** monkey patch Widget **
恕我直言,我会做的是创建一个函数:
def fire_my_event(widget):
if hasattr(widget, 'on_test_event'):
if widget.on_test_event():
return True
for c in widget.children[:]:
if fire_my_event(c):
return True
#in your code somewhere
class SomeWidget(Image): #or anything else ...
def on_touch_down(self, touch):
fire_my_event(self)
玩得开心!