Search code examples
kivy

kivy touch events bubbling and overriding on_ methods


The pictures example in /share/kivy-examples/demo/pictures places Image widget in Scatter. I'd like to extend the example and replace Image with <ImageButton@ButtonBehavior+Image>. However, the touch events are not implemented correctly. The ImageButtons are press-able but the drag functionality from the original example is lost.

At first I simply changed Image to <ImageButton@ButtonBehavior+Image> in the pictures.kv file. I see in the documentation that I may need to (re)implement on-press or on_touch_down. To that end, I've added these methods in the Picture class:

class Picture(Scatter):

    source = StringProperty(None)

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            print('picture touch down')
        else:
            print('no collide in picture')
        super(Picture, self).on_touch_down(touch)
    def on_touch_move(self, touch):
        if self.collide_point(*touch.pos):
            print('touch move')
            super(Picture, self).on_touch_move(touch)

I see the print statements in the terminal. But the ImageButtons are still consuming the on_press, and I know this from a print statement in that event handler. I tried to re-implement on_press and just not do anything with pass, and then I had an idea of calling self.parent.on_touch_down, but I don't have a touch object to pass into it. One idea would be to

class ImageButton(ButtonBehavior, Image):
    '''
    def on_press(self):
        print("button pressed")
        print()
        return super(ImageButton, self).on_press()
    '''
    def on_press(self):
        pass

So, say I want the ImageButton to only register a double-clicks, and otherwise, for the widgets to behave just like in the example. How would I achieve that? Somewhat related


Solution

  • While there may be a way of distinguishing between a quick touch_down followed immediately by a touch_up, it is easier to show the desired functionality by letting an ImageButton press be activated with a double_tap:

    class ImageButton(ButtonBehavior, Image):
        def __init__(self, **kwargs):
            super(ImageButton, self).__init__(**kwargs)
        def on_touch_down(self, touch):
            if self.collide_point(*touch.pos) and touch.is_double_tap:
                self.on_press(touch)
                return True
            return False
        def on_press(self,touch):
            #whatever else you want to happen 
            return True