# animation.py # Walker M. White (wmw2) # November 8, 2012 """Module to show off a touch application. Touch events are broken into three broad categories: on_touch_down: use recently pressed the mouse/finger on_touch_up: user released mouse/finger on_touch_move: used moved mouse/finger while holds it down. All three of these are a necessary part of a touch application.""" from kivy.uix.floatlayout import FloatLayout from kivy.uix.boxlayout import BoxLayout from kivy.graphics.vertex_instructions import Line, Rectangle, Ellipse from kivy.graphics.context_instructions import Color from kivy.properties import ObjectProperty from kivy.factory import Factory from kivy.config import Config from kivy.app import App # RGB Colors for our various drawings LINE_COLOR = Color(1,0,0) SPOT_COLOR = Color(0,0,1) SPOT_RADIUS = 20 class TouchPanel(FloatLayout): """Drawing canvas to display the shape.""" # Necessary fields to represent state # Coordinates of last touch event # Invariant: 2-element tuple of float or None. If None, either _state # is 'spots' or the mouse/finger is not down. _anchor = None # Current shape to draw # Invariant: Either 'line' or 'spots' _state = 'line' def drawLine(self,x0,y0,x1,y1,color): """Draw a line from (x0,y0) to (x1,y1) of the given color. Precondition: x0, y0, x1, y1 are all floats. color is a Kivy color object.""" self.canvas.add(color) self.canvas.add(Line(points=[x0,y0,x1,y1],width=2)) def drawSpot(self,x,y,color): """Draw a circle of radius SPOT_RADIUS centered at (x,y) with the given color. Precondition: x, y are both floats. color is a Kivy color object.""" self.canvas.add(color) self.canvas.add(Ellipse(pos=(x-SPOT_RADIUS/2.0,y-SPOT_RADIUS/2.0),size=(SPOT_RADIUS,SPOT_RADIUS))) def setState(self,state): """Change the state of this drawing panel to state. Changing the state automatically sets the _anchor to None. Precondition: state is one of 'line' or 'spots' """ assert state == 'line' or state == 'spots', `state`+' is an invalid state' self._state = state self._anchor = None # Work around for weird bug I do not understand. self.canvas.ask_update() def on_touch_down(self,touch): """Called when the user presses the mouse or a finger (on touch screens) Precondition: touch is a Kivy MotionEvent object""" print 'Touch down at point '+str((touch.x,touch.y)) # Only need to track previous touches if drawing lines. if self._state == 'line': self._anchor = (touch.x,touch.y) elif self._state == 'spots': # Spots can be drawn immediately self.drawSpot(touch.x,touch.y,SPOT_COLOR) def on_touch_up(self,touch): """Called when the user releases the mouse or a finger (on touch screens) Precondition: touch is a Kivy MotionEvent object""" print 'Touch up at point '+str((touch.x,touch.y)) # Only need to track previous touches if drawing lines. if self._state == 'line': self._anchor = None def on_touch_move(self,touch): """Called when the user moves the mouse or a finger (on touch screens) Precondition: touch is a Kivy MotionEvent object""" print 'Touch move to point '+str((touch.x,touch.y)) # Only need to track previous touches if drawing lines. if self._state == 'line' and not self._anchor is None: self.drawLine(self._anchor[0],self._anchor[1],touch.x,touch.y,LINE_COLOR) self._anchor = (touch.x,touch.y) elif self._state == 'spots': # Just draw a spot in place self.drawSpot(touch.x,touch.y,SPOT_COLOR) class TouchMain(BoxLayout): """Main panel with buttons. Defined entirely in the touch.kv file.""" # Kivy property for coordination with .kv file. panel = ObjectProperty(None) class TouchApp(App): """Instance is an application that draws according to touch.""" def build(self): """Build application with a single internal panel""" """Build application with a single internal panel""" Config.set('graphics', 'width', '400') Config.set('graphics', 'height', '400') return TouchMain(size=(400,400)) # Register UI elements for .kv files. Factory.register("TouchPanel", TouchPanel) # Application Code if __name__ == '__main__': TouchApp().run()