29. Drawing on a canvas
[status: content-mostly-written]
Prerequisites
The 10-hour “serious programming” course.
A GNU/Linux system with python3 and python3-tk installed (on an Ubuntu 16.04 system this can be done with
sudo apt install python3-tk
)
29.1. Simplest canvas
Drawing is usually done with the help of a graphical toolkit library.
This library usually supports widgets and allows them to be arranged
in a window on the scren. The widget for drawing is called a canvas
and in Listing 29.1.1 is a simple example using
Python’s tkinter
widget set.
#! /usr/bin/env python3
"""simple canvas with two discs and a line between them
"""
## we use the tkinter widget set; this seems to come automatically
## with python3 on ubuntu 16.04, but on some systems one might need to
## install a package with a name like python3-tk
from tkinter import *
canvas_width = 640
canvas_height = 480
def main():
## prepare a basic canvas
root = Tk()
w = Canvas(root,
width=canvas_width,
height=canvas_height)
w.pack() # boiler-plate: we always call pack() on tk windows
w.create_oval(210, 230, 230, 250, fill="yellow")
w.create_oval(410, 230, 430, 250, fill="blue")
w.create_line(220, 240, 420, 240)
mainloop()
main()
Things to notice about this program:
It uses the library
tkinter
which provides calls to create a window and draw things in it.The calls
root = Tk()
andw.pack()
andmainloop
are boiler-plate: almost all programs that use the tkinter toolkit will use them.w = Canvas(...)
creates a canvas with the given width and height.w.pack()
places that canvas into the window we are using.After the drawing calls
create_oval()
andcreate_line()
we callmainloop()
. This enters an event loop in which the widget set is waiting for events, such as the click of a button. We have not created any buttons, somainloop()
will just hang until we interrupt the progrma.
29.2. Simplest animation
Animation can be done simply by drawing onto a canvas, then changing the drawing after a small amount of time and refreshing the canvas.
In listing Listing 29.2.1
#! /usr/bin/env python3
"""simple animation of a growing/contracting disc
"""
import time
import math
## we use the tkinter widget set; this seems to come automatically
## with python3 on ubuntu 16.04, but on some systems one might need to
## install a package with a name like python3-tk
from tkinter import *
canvas_width = 640
canvas_height = 480
def main():
## prepare a basic canvas
root = Tk()
w = Canvas(root,
width=canvas_width,
height=canvas_height)
w.pack() # boiler-plate: we always call pack() on tk windows
for i in range(24*180): # 3 minutes if it's 24 frames/sec
radius = 140 + 50*math.sin(i/24.0) # oscillating radius
center = (canvas_width/2, canvas_height/2)
color = 'blue'
## clear the canvas and then draw a new disc
w.delete('all')
w.create_oval(center[0]-radius, center[1]-radius,
center[0]+radius, center[1]+radius,
fill=color)
## update the canvas
w.update()
time.sleep(1.0/24.0) # 24 frames per second
mainloop()
main()
Note that this kind of animation is not ideal: it works well, but it
does not allow the program to respond to any user input or other
events. For us this is OK because we are purely showing the
animation, and we are not setting up any buttons or other parts to the
program, but the tkinter
library offers a more appropriate
approach to doing animations with a method called after()
which
allows you to call your drawing routines and handle user interface
events at the same time.
29.2.1. Exercises
Modify the tirial animation program in Listing 29.2.1 to write the current at the bottom of the canvas. A web search for “tkinter write string on canvas” might help.
Study how colors can be represented as combinations of red, green and blue (RGB) values. Read the introductory part of the Wikipedia article on the subject at https://en.wikipedia.org/wiki/RGB_color_model and then use the program gpick to examine how the various screen pixel colors can be represented as red, green and blue. Explore the program in detail, looking at how you can specify the RGB values and see what the result is, but you can also pick them from a color wheel, and you also use the screen picker FIXME…
Modify the trivial animation program in
Listing 29.2.1 to cycle through the colors
as well as the radius. Aim for a psychadelic effect. Note that
the fill=
field in create_oval()
can be a descriptive color
name (like the "blue"
that we used) but it can also specify the
RGB (red, green, blue) values that form the color. A web search
for “tkinter colors” might help.