2016-10-09 3 views
2

Beginnen wir mit dem Grund Beispiel entsendet:Erstellen Kivy Verhalten, das Ereignis sprudeln genauso wie 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) 

Ereignis Versendungen in OuterWidget zuerst, wenn es super().on_touch_down(touch) Ereignis ruft die Versendungen in Kind-Widgets, sonst -Ereignis nicht weiter . Das ist klar.

Ich möchte etwas Verhalten erstellen, das mit on_touch_down passiert und auf die gleiche Weise handelt. Lassen Sie uns versuchen:

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 Sprudeln nicht genauso wie on_touch_down funktionieren würde. Unabhängig davon, was OuterWidget zurückgibt Ereignis würde an InnerWidget gesendet werden. Es passiert, weil beide Widgets on_touch_down Ereignis erhalten, das on_test_event feuert.

Sieht aus, als wenn ich on_touch_down verwenden, um ein Ereignis im Verhalten zu senden, wird dieses Ereignis immer an alle Kinder gesendet, unabhängig davon, was von ihnen zurückgegeben wurde. Aber ich möchte nicht on_test_event nächste versenden, wenn einige Widget super().on_test_event(touch) nicht aufgerufen haben.

Wie kann ich es tun? Irgendwelche Ideen?

Antwort

2

Die Widget-Klasse behandelt ihre Veranstaltungen für alle seine Kinder wie folgt aus:

(von widget.py kopiert)

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 

Wie Sie seine childern sehen es iteriert und schicken das Ereignis bis True wird zurückgegeben.

Um ein ähnliches Verhalten erstellen Sie Ihre eigenen Mix-in-Klasse erstellen können und alle von ihm inhärenten Sie Klasse machen oder ** Affe Patch Widget **

IMHO, die ein bisschen chaotisch sein wird, was Ich würde tun, um eine Funktion zu erstellen:

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) 

Viel Spaß!

Verwandte Themen