Button Events: on_press or on_release
on_press and on_release events are bindable to Button widget. We can use on_touch_down to simulate on_press event and on_touch_up to simulate on_release event.
Event: on_touch_down
Use on_touch_down event, check for collision of the touch with our widget, and check for button profile. If button profile, check for mouse button click, or mouse wheel scrolling (scrollup or scrolldown). If button clicked, grab touch event, increment touch event counter, and start repeat zoom.
Event: on_touch_up
Use on_touch_up event, check the touch event has been grabbed, ungrab touch event if it was grabbed, decrement touch event counter, and if touch event counter is zero, stop repeat zoom.
Snippets
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
if 'button' in touch.profile:
if touch.button in ("right", "left"):
...
dist = 1 if touch.button == 'left' else -1
touch.grab(self)
self._touch_count += 1
...
return True
elif touch.is_mouse_scrolling:
dist = 1 if touch.button == 'scrollup' else -1
...
return True
return super(..., self).on_touch_down(touch)
def on_touch_up(self, touch):
if touch.grab_current == self:
touch.ungrab(self)
self._touch_count -= 1
if self._touch_count == 0:
print("\tanimate to the closest zoom")
return True
return super(RootWidget, self).on_touch_up(touch)
Programming Guide » Input management » Touch event basics
By default, touch events are dispatched to all currently displayed
widgets. This means widgets receive the touch event whether it occurs
within their physical area or not.
In order to provide the maximum flexibility, Kivy dispatches the
events to all the widgets and lets them decide how to react to them.
If you only want to respond to touch events inside the widget, you
simply check for collision.
Motion Event » Profiles
Profile value: button
Description: Mouse button (‘left’,
‘right’, ‘middle’, ‘scrollup’ or ‘scrolldown’). Accessed via the
button property.
is_mouse_scrolling
Returns True if the touch is a mousewheel scrolling
Example
main.py
from math import sin
from kivy.garden.graph import Graph, MeshLinePlot
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import NumericProperty
class RootWidget(BoxLayout):
_touch_count = NumericProperty(0)
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
self.graph = Graph(xlabel='X', ylabel='Y', x_ticks_minor=5,
x_ticks_major=25, y_ticks_major=1,
y_grid_label=True, x_grid_label=True, padding=5,
x_grid=True, y_grid=True, xmin=-0, xmax=100, ymin=-1, ymax=1)
plot = MeshLinePlot(color=[1, 0, 0, 1])
plot.points = [(x, sin(x / 10.)) for x in range(0, 101)]
self.graph.add_plot(plot)
self.add_widget(self.graph)
def on_touch_down(self, touch):
"""
If the touch falls inside of our widget, we check button profile. If mouse button click, we set dist to 1 for
left mouse button clicked else -1 for right mouse button clicked. If not mouse button click, we check for mouse
wheel scrolling. If mouse is scrolling, we set dist to 1 if scrollup else -1 for scrolldown. If mouse button
clicked or mouse wheel scrolling, we return True, indicating that we have consumed the touch and don’t want it
to propagate any further.
Finally, if the touch falls outside our widget, not mouse button clicked (left / right button clicked), or not
mouse wheel scrolling, we call the original event using super(…) and return the result. This allows the touch
event propagation to continue as it would normally have occurred.
:param touch:
:return:
"""
print("\non_touch_down:")
if self.collide_point(*touch.pos):
if 'button' in touch.profile:
if touch.button in ("right", "left"):
print("\t", touch.button, "mouse clicked")
print("\ttouch.pos =", touch.pos)
dist = 1 if touch.button == 'left' else -1
self.zoom(dist)
return True
elif touch.is_mouse_scrolling:
print("\tmouse wheel", touch.button)
print("\ttouch.pos =", touch.pos)
dist = 1 if touch.button == 'scrollup' else -1
self.zoom(dist)
return True
return super(RootWidget, self).on_touch_down(touch)
def on_touch_up(self, touch):
print("\non_touch_up:")
if touch.grab_current == self:
print("\ttouch.button is", touch.button)
print("\ttouch.pos is", touch.pos)
touch.ungrab(self)
self._touch_count -= 1
if self._touch_count == 0:
# TODO
print("\tanimate to the closest zoom")
return True
return super(RootWidget, self).on_touch_up(touch)
def zoom(self, dist):
self.graph.xmax += dist * 10
self.graph.xmin += dist
class GraphDemo(App):
def build(self):
return RootWidget()
if __name__ == "__main__":
GraphDemo().run()
Output
