/examples/demo/touchtracer/main.py
https://github.com/kivy/kivy · Python · 170 lines · 156 code · 5 blank · 9 comment · 3 complexity · 78da4aaedc16b46f6296493133860342 MD5 · raw file
- '''
- Touch Tracer Line Drawing Demonstration
- =======================================
- This demonstrates tracking each touch registered to a device. You should
- see a basic background image. When you press and hold the mouse, you
- should see cross-hairs with the coordinates written next to them. As
- you drag, it leaves a trail. Additional information, like pressure,
- will be shown if they are in your device's touch.profile.
- .. note::
- A function `calculate_points` handling the points which will be drawn
- has by default implemented a delay of 5 steps. To get more precise visual
- results lower the value of the optional keyword argument `steps`.
- This program specifies an icon, the file icon.png, in its App subclass.
- It also uses the particle.png file as the source for drawing the trails which
- are white on transparent. The file touchtracer.kv describes the application.
- The file android.txt is used to package the application for use with the
- Kivy Launcher Android application. For Android devices, you can
- copy/paste this directory into /sdcard/kivy/touchtracer on your Android device.
- '''
- __version__ = '1.0'
- import kivy
- kivy.require('1.0.6')
- from kivy.app import App
- from kivy.uix.floatlayout import FloatLayout
- from kivy.uix.label import Label
- from kivy.graphics import Color, Rectangle, Point, GraphicException
- from kivy.metrics import dp
- from random import random
- from math import sqrt
- def calculate_points(x1, y1, x2, y2, steps=5):
- dx = x2 - x1
- dy = y2 - y1
- dist = sqrt(dx * dx + dy * dy)
- if dist < steps:
- return
- o = []
- m = dist / steps
- for i in range(1, int(m)):
- mi = i / m
- lastx = x1 + dx * mi
- lasty = y1 + dy * mi
- o.extend([lastx, lasty])
- return o
- class Touchtracer(FloatLayout):
- def normalize_pressure(self, pressure):
- print(pressure)
- # this might mean we are on a device whose pressure value is
- # incorrectly reported by SDL2, like recent iOS devices.
- if pressure == 0.0:
- return 1
- return dp(pressure * 10)
- def on_touch_down(self, touch):
- win = self.get_parent_window()
- ud = touch.ud
- ud['group'] = g = str(touch.uid)
- pointsize = 5
- print(touch.profile)
- if 'pressure' in touch.profile:
- ud['pressure'] = touch.pressure
- pointsize = self.normalize_pressure(touch.pressure)
- ud['color'] = random()
- with self.canvas:
- Color(ud['color'], 1, 1, mode='hsv', group=g)
- ud['lines'] = [
- Rectangle(pos=(touch.x, 0), size=(1, win.height), group=g),
- Rectangle(pos=(0, touch.y), size=(win.width, 1), group=g),
- Point(points=(touch.x, touch.y), source='particle.png',
- pointsize=pointsize, group=g)]
- ud['label'] = Label(size_hint=(None, None))
- self.update_touch_label(ud['label'], touch)
- self.add_widget(ud['label'])
- touch.grab(self)
- return True
- def on_touch_move(self, touch):
- if touch.grab_current is not self:
- return
- ud = touch.ud
- ud['lines'][0].pos = touch.x, 0
- ud['lines'][1].pos = 0, touch.y
- index = -1
- while True:
- try:
- points = ud['lines'][index].points
- oldx, oldy = points[-2], points[-1]
- break
- except IndexError:
- index -= 1
- points = calculate_points(oldx, oldy, touch.x, touch.y)
- # if pressure changed create a new point instruction
- if 'pressure' in ud:
- old_pressure = ud['pressure']
- if (
- not old_pressure
- or not .99 < (touch.pressure / old_pressure) < 1.01
- ):
- g = ud['group']
- pointsize = self.normalize_pressure(touch.pressure)
- with self.canvas:
- Color(ud['color'], 1, 1, mode='hsv', group=g)
- ud['lines'].append(
- Point(points=(), source='particle.png',
- pointsize=pointsize, group=g))
- if points:
- try:
- lp = ud['lines'][-1].add_point
- for idx in range(0, len(points), 2):
- lp(points[idx], points[idx + 1])
- except GraphicException:
- pass
- ud['label'].pos = touch.pos
- import time
- t = int(time.time())
- if t not in ud:
- ud[t] = 1
- else:
- ud[t] += 1
- self.update_touch_label(ud['label'], touch)
- def on_touch_up(self, touch):
- if touch.grab_current is not self:
- return
- touch.ungrab(self)
- ud = touch.ud
- self.canvas.remove_group(ud['group'])
- self.remove_widget(ud['label'])
- def update_touch_label(self, label, touch):
- label.text = 'ID: %s\nPos: (%d, %d)\nClass: %s' % (
- touch.id, touch.x, touch.y, touch.__class__.__name__)
- label.texture_update()
- label.pos = touch.pos
- label.size = label.texture_size[0] + 20, label.texture_size[1] + 20
- class TouchtracerApp(App):
- title = 'Touchtracer'
- icon = 'icon.png'
- def build(self):
- return Touchtracer()
- def on_pause(self):
- return True
- if __name__ == '__main__':
- TouchtracerApp().run()