簡體   English   中英

創建 kivy 行為,以與 on_touch_down 相同的方式調度事件冒泡

[英]Creating kivy behavior that dispatches event bubbling same way as on_touch_down

讓我們從基本示例開始:

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_test_event on_touch_down事件。

看起來如果我使用on_touch_down來調度某個行為的事件,這個事件將始終被調度給所有孩子,無論他們返回什么。 但是如果某個小部件沒有調用super().on_test_event(touch)我不想接下來調度on_test_event

我該怎么做? 有任何想法嗎?

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

正如您所看到的,它遍歷其子進程並分派事件,直到返回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)

玩得開心!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM