17.7. The Canvas Widget
Class Canvas is a powerful, flexible widget used for many purposes, including plotting and, in particular, building custom widgets. Building custom widgets is an advanced topic, and I do not cover it further in this book. This section covers only a subset of Canvas functionality used for the simplest kind of plotting.
Coordinates within a Canvas instance c are in pixels, with origin at the upper-left corner of c, and positive coordinates growing rightward and down. Some advanced methods let you change c's coordinate system, but I do not cover them in this book.
What you draw on a Canvas instance c are canvas
items: lines, polygons, Tkinter images, arcs, ovals, texts, and others. Each item has an item handle by which you can refer to the item. You can also assign symbolic names called tags to sets of canvas items (the sets of items with different tags can overlap). ALL is a predefined tag that applies to all items; CURRENT is a predefined tag that applies to the item under the mouse pointer.
Tags on a Canvas are different from tags on a Text. Canvas tags are nothing more than sets of items, with no independent existence. When you perform any operation with a Canvas tag as the item identifier, the operation occurs on the items that are in the tag's current set. It makes no difference if items are later removed from or added to that tag.
To create a canvas item, call on c a method with a name of the form create_kindofitem, which returns the new item's handle. Methods itemcget and itemconfig of c let you get and change items' options.
17.7.1. Canvas Methods on Items
A Canvas instance c supplies methods that you can call on items. The item argument can be an item's handleas returned, for example, by c.create_lineor a tag, meaning all items in that tag's set (no items at all if the tag's set is currently empty), unless otherwise indicated in the method's description.
bbox | c.bbox(item)
Returns an approximate bounding box for item, which is a tuple of four integers: the pixel coordinates of minimum x, minimum y, maximum x, and maximum y, in that order. For example, c.bbox(ALL) returns the minimum and maximum x and y coordinates of all items on c. When c has no items at all, c.bbox(ALL) returns None.
| coords | c.coords(item,*coordinates)
Changes the coordinates for item. Operates on just one item. If item is a tag, coords operates on an arbitrary item currently in the tag's set. If item is a tag with an empty set, coords is an innocuous no-operation.
| delete | c.delete(item)
Deletes item. For example, c.delete(ALL) deletes all items on c.
| gettags | c.gettags(item)
Returns the sequence of all tags whose sets include item (but not tag ALL, which includes all items, nor CURRENT, whether or not it includes item).
| itemcget | c.itemcget(item,option)
Returns the value of option for item. Operates on just one item. If item is a tag, itemcget returns the value of option for an arbitrary item currently in the tag's set. If item is a tag with an empty set, itemcget returns the empty string ''.
| itemconfig | c.itemconfig(item,**options)
Sets or changes the value of options for item. For example, c.itemconfig(ALL, fill='red') sets all items on c to fill-color red.
| tag_bind | c.tag_bind(tag,event_name,callable[,'+'])
c.tag_bind(tag,event_name,callable) sets callable as the callback for event_name on the items currently in tag's set. c.tag_bind(tag,event_name,callable,'+') adds callable to the previous bindings. Events, callbacks, and bindings are covered in "Tkinter Events" on page 446.
| tag_unbind | c.tag_unbind(tag,event)
c.tag_unbind(tag,event) removes bindings for event on the items currently in tag's set. Events and bindings are covered in "Tkinter Events" on page 446.
|
17.7.2. The Line Canvas Item
A Canvas instance c supplies one method to create a line item.
create_line | c.create_line(*coordinates, **line_options)
Creates a line item with vertices at given coordinates and returns the item's handle. coordinates must be an even number of positional parameters, alternately x and y for each vertex of the line. Coordinates are in pixels, with origin (0,0) in the upper-left corner, x growing rightward, and y growing downward. You may set different coordinate systems on c, but I do not cover this option in this book. line_options may include:
arrow
Which ends of the line have arrow heads: NONE (default), FIRST, LAST, or BOTH
fill
The line's color (default is black)
smooth
If true, the line is drawn as a smooth curve (a B-spline); otherwise (default), the line is drawn as a polygonal (a sequence of line segments)
tags
A string to set one tag on the item or a tuple of strings to set multiple tags on the item
width
Width of the line in pixels (default is 1)
For example:
-
x=c.create_line(0,150, 50,100, 0,50, 50,0 smooth=1)
draws an S-like curve on c, binding the curve's handle to name x. You can then change the curve's color to blue with:
c.itemconfig(x,fill='blue')
|
17.7.3. The Polygon Canvas Item
A Canvas instance c supplies one method to create a polygon item.
create_polygon | c.create_polygon(*coordinates, **poly_options)
Creates a polygon item with vertices at the given coordinates and returns the item's handle. coordinates must be an even number of positional parameters, alternately x and y for each vertex of the polygon, and there must be at least six positional parameters (at least three vertices). poly_options may include:
fill
The polygon's interior color (default is black)
outline
The polygon's perimeter color (default is black)
smooth
If true, the polygon is drawn as a smooth curve (a B-spline); otherwise (default), the line is drawn as a normal polygon (a sequence of sides)
tags
A string to set one tag on the item or a tuple of strings to set multiple tags on the item
width
Width of the perimeter line in pixels (default 1)
For example:
-
x=c.create_polygon(0,150, 50,100, 0,50, 50,0, fill='',
outline='red')
draws two empty red triangles on c as a single polygon and binds the polygon's handle to name x. You can then fill the triangles with blue using:
c.itemconfig(x,fill='blue')
|
17.7.4. The Rectangle Canvas Item
A Canvas instance c supplies one method to create a rectangle item.
create_rectangle | c.create_rectangle(x0,y0,x1,y1,**rect_options)
Creates a rectangle item with vertices at the given coordinates and returns the item's handle. rect_options may include:
fill
The rectangle's interior color (default is empty)
outline
The rectangle's perimeter color (default is black)
tags
A string to set one tag on the item or a tuple of strings to set multiple tags on the item
width
Width of the perimeter line in pixels (default is 1)
|
17.7.5. The Text Canvas Item
A Canvas instance c supplies one method to create a text item.
create_text | c.create_text(x,y,**text_options)
Creates a text item at the given x and y coordinates and returns the item's handle. text_options may include:
anchor
The exact spot of the text's bounding box that x and y refer to; may be N, E, S, W, NE, NW, SE, or SWwhich are compass directions that indicate the corners and sides of the bounding boxor CENTER (the default)
fill
The text's color (default is black)
font
Font to use for this text
tags
A string to set one tag on the item or a tuple of strings to set multiple tags on the item
text
The text to display
|
17.7.6. A Simple Plotting Example
The following example shows how to use a Canvas to perform an elementary plotting task, graphing a user-specified function:
from Tkinter import *
import math
root = Tk( )
# first, a row for function entry and action button fram = Frame(root)
Label(fram,text='f(x):').pack(side=LEFT)
func = Entry(fram)
func.pack(side=LEFT, fill=BOTH, expand=1)
butt = Button(fram, text='Plot')
butt.pack(side=RIGHT)
fram.pack(side=TOP)
# then a row to enter bounds in fram = Frame(root)
bounds = [ ]
for label in 'minX', 'maxX', 'minY', 'maxY':
Label(fram,text=label+':').pack(side=LEFT)
edit = Entry(fram, width=6)
edit.pack(side=LEFT)
bounds.append(edit)
fram.pack(side=TOP)
# and finally the canvas c = Canvas(root)
c.pack(side=TOP, fill=BOTH, expand=1)
def minimax(values=[0.0, 1.0, 0.0, 1.0]):
"Adjust and display X and Y bounds"
for i in range(4):
edit = bounds[i]
try: values[i] = float(edit.get( ))
except: pass
edit.delete(0, END)
edit.insert(END, '%.2f'%values[i])
return values
def plot( ):
"Plot given function with given bounds"
minx, maxx, miny, maxy = minimax( )
# get and compile the function
f = func.get( )
f = compile(f, f, 'eval')
# get Canvas X and Y dimensions
CX = c.winfo_width( )
CY = c.winfo_height( )
# compute coordinates for line
coords = [ ]
for i in range(0,CX,5):
coords.append(i)
x = minx + ((maxx-minx)*i)/CX
y = eval(f, vars(math), {'x':x})
j = CY - CY*(y-miny)/(maxy-miny)
coords.append(j)
# draw line
c.delete(ALL)
c.create_line(*coords)
butt.config(command=plot)
# give an initial sample in lieu of docs f = 'sin(x) + cos(x)'
func.insert(END, f)
minimax([0.0, 10.0, -2.0, 2.0])
root.mainloop( )
Figure 17-2 shows the output that results from this example.
![](images/pixel.jpg) |