Previous Section Next Section

16.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 the origin at the upper left corner of c and positive coordinates growing rightward and downward. There are advanced methods that 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, which can be 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 instance are different from tags on a Text instance. The canvas tags are nothing more than sets of items with no independent existence. When you perform any operation, passing a Canvas tag as the item identifier, the operation occurs on those items that are in the tag's current set. It makes no difference if items are later removed from or added to that tag's set.

You create a canvas item by calling 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.

16.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 handle, as returned for example by c.create_line, or a tag, meaning all items in that tag's set (or 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, a tuple of four integers: the pixel coordinates of minimum x, minimum y, maximum x, maximum y, in this 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 one of the items 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 one of the items 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 color red.

tag_bind

c.tag_bind(tag,event_name,callable[,'+'])

c.tag_bind(tag,event_name,callable) sets callable as the callback object for event_name on the items currently in tag's set. Calling c.tag_bind(tag,event_name,callable,'+') adds callable to the previous bindings. Events, callbacks, and bindings are covered in Section 16.9 later in this chapter.

tag_unbind

c.tag_unbind(tag,event)

c.tag_unbind(tag,event) removes any binding for event on the items currently in tag's set. Events and bindings are covered in Section 16.9 later in this chapter.

16.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 the given coordinates and returns the item's handle. coordinates must be an even number of positional parameters, alternately x and y values for each vertex of the line. Canvas coordinates, by default, are in pixels, with the origin (coordinates 0,0) in the upper left corner, the x coordinate growing rightward, and the y coordinate growing downward. You may set different coordinate systems on c, but I do not cover these possibilities in this book. line_options may include:

arrow

Sets which ends of the line have arrow heads; may be 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 assign a single tag to this item) or a tuple of strings (to assign multiple tags to this item)

width

Width of the line in pixels (default 1)

For example:

x=c.create_line(0,150, 50,100, 0,50, 50,0 smooth=1)

draws a somewhat S-like curve on c, and binds the curve's handle to variable x. You can then change the curve's color to blue with:

c.itemconfig(x,fill='blue')

16.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 values for each vertex of the polygon, and there must be at least six positional parameters (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 assign a single tag to this item) or a tuple of strings (to assign multiple tags to this 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 variable x. You can then fill the triangles with blue using:

c.itemconfig(x,fill='blue')

16.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 assign a single tag to this item) or a tuple of strings (to assign multiple tags to this item)

width

Width of the perimeter line in pixels (default 1)

16.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 SW, compass directions indicating the corners and sides of the bounding box, or CENTER (the default)

fill

The text's color (default is black)

font

Font to use for this text

tags

A string (to assign a single tag to this item) or a tuple of strings (to assign multiple tags to this item)

text

The text to display

16.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*(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 16-2 shows the output resulting from this example.

Figure 16-2. A sample Canvas
figs/pynut_1602.gif
    Previous Section Next Section