Events and Animation: The Bouncing Square

So far, the Tkinter’s canvas widget has made drawing squares, circles, text, and even nyan
Poptart cats, practical and relatively straightforward. Now its time to animate our canvas
Global Vs. Local Canvas
!e’ve now see two ways of accessing our canvas in the various functions that might need
it" storing the widget’s information within a glo#al dictionary, or declaring the canvas
widget itself as glo#al. !hen displaying many o#$ects on a canvas, however, we need a way
to store the information of each o#$ect %perhaps its location or color& for easy access later.
!e’ll use a glo#al dictionary for our #ouncing square example.
The init Function
!hen using a canvas in python, ' lines need to #e present nearly every time"
from Tkinter import (
root ) Tk
canvas ) *anvas%root, width ) foo, height ) #ar&
canvas.pack%&
root.mainloop%&
+ow we organi,e these %and all su#sequent lines& is highly flexi#le, however. -n a complex
animation, it’s a good idea to have a run function handle these initiali,ing steps, like so"
from Tkinter import (
def run%&"
root ) Tk
canvas ) *anvas%root, width ) foo, height ) #ar&
canvas.pack%&
root.mainloop%&
run%&
.or our #ouncing square example, there are quite a few varia#les we need to keep track of,
including where our square is at any given moment, how large our square is, what color,
etc. !e’ll create a glo#al dictionary to keep track of all this data, and to change some as
needed.
from Tkinter import (
def run%&"
root ) Tk
Events and Animation: The Bouncing Square
foo ) *anvas%root, width ) foo, height ) #ar&
canvas.pack%&
glo#al data
data ) /0
data12canvas34 ) foo
root.mainloop%&
run%&
This is not enough, however" with so many varia#les, it might #e a good idea to have a
function that initiali,es this type of information, so when we first draw the square %#efore
it moves at all&, everything exists. !e call this an init function, and it might look like this"
from Tkinter import (
def init%&"
glo#al data
data12square*olor34 ) 2#lue5
data12square6eft34 ) '7
data12squareTop34 ) '7
data12squareSi,e34 ) '7
def run%&"
root ) Tk
foo ) *anvas%root, width ) foo, height ) #ar&
foo.pack%&
glo#al data
data ) /0
data12canvas34 ) foo
init%&
root.mainloop%&
run%&
The redraAll !unction
!ith our square’s starting point esta#lished, it would #e nice to see the square. To clear off
the canvas of old images, we would need to call foo.delete%866&, and then draw the square
#ased off the data saved in the glo#al dictionary. 9emem#er that the syntax for drawing a
square looks like this, where foo is the canvas, left:right:top:#ottom are integers, and
color is a string"
foo.create;rectangle%left, top, right, #ottom, fill)color&
Events and Animation: The Bouncing Square
Timer Fired
8#le to draw our square, we need to keep it moving across the canvas. 8 function that
serves as a timer would #e handy<perhaps using foo.after%delay, function& would help=
+aving the function, timer.ired, change the data from which we draw our square, as well as
having it call redraw8ll, would #e nice 8n example, where doTimer.ired is provided code
that moves the square’s data"
def timer.ired%&"
glo#al data
foo ) data12foo34
doTimer.ired%&
redraw8ll%&
delay ) '7
foo.after%delay, timer.ired&
Let"s #ut it all together$
from Tkinter import (
def run%&"
root ) Tk%&
w ) >77
h ) '77
foo ) *anvas%root, width)w, height)h&
foo.pack%&
glo#al data
data ) /0
data12foo34 ) foo
data12w34 ) w
data12h34 ) h
init%&
timer.ired%&
root.mainloop%&
def init%&"
glo#al data
data12square*olor34 ) 2#lue5
data12square6eft34 ) '7
Events and Animation: The Bouncing Square
data12squareTop34 ) '7
data12squareSi,e34 ) '7
data12counter34 ) 7
data12going934 ) True
data12going?34 ) .alse
def timer.ired%&"
glo#al data
foo ) data12foo34
doTimer.ired%&
redraw8ll%&
delay ) '7
foo.after%delay, timer.ired&
def doTimer.ired%&"
glo#al data
if data12going934"
if %data12square6eft34 @ data12squareSi,e34 A data13w34&"
data12going934 ) .alse
else"
move9ight%&
else"
if %data12square6eft34 B 7&"
data12going934 ) True
else"
move6eft%&
if data12going?34"
if %data12squareTop34 @ data12squareSi,e34 A data13h34&"
data12going?34 ) .alse
else"
move?own%&
else"
if %data12squareTop34 B 7&"
data12going?34 ) True
else"
moveCp%&
def move6eft%&"
glo#al data
data12square6eft34 D) E7
def move9ight%&"
glo#al data
Events and Animation: The Bouncing Square
data12square6eft34 @) E7
def moveCp%&"
glo#al data
data12squareTop34 D) E7
def move?own%&"
glo#al data
data12squareTop34 @) E7
def redraw8ll%&"
glo#al data
data12foo34.delete%866&
data12foo34.create;rectangle%data12square6eft34,
data12squareTop34,
data12square6eft34 @ data12squareSi,e34,
data12squareTop34 @ data12squareSi,e34,
fill)data12square*olor34&
run%&