Simple Graphics

A canvas is a rectangular area within a window in which the programmer can perform graphics operations, such as drawing geometric shapes, text, and so forth.  A canvas can also detect mouse events, such as button presses and releases, mouse cursor movement, and mouse dragging (pressing mouse button and moving the mouse cursor simultaneously).  Canvases are useful for decorating windows, displaying graphs and charts, developing interactive sketchpads, and other graphics-based applications.

A canvas uses a screen coordinate system.  Unlike the Cartesian coordinate system, the origin (0,0) for screen coordinates is in the upper left corner of the drawing area.  The x-axis and is at the top boundary of the canvas and the y-axis is its the left boundary.  The x values increase to the right, as usual, but the y values increase to the bottom.  For example, the point (50, 50) is located 50 pixels to the right of the y-axis and 50 pixels below the x-axis.  Negative coordinates exist but are not viewable outside of the boundaries of a canvas.  The window can be resized to view positive coordinates that lie beyond the current right and bottom boundaries of a canvas.

The primary canvas resource in breezypythongui is the EasyCanvas class.  This class provides all of the capabilities of PythonÕs tkinter.canvas, as well as some useful extensions.  These extensions allow the beginner to draw simple geometric shapes and text, as well as respond to mouse events. 

There are two basic design patterns for adding canvasses to an application.  The first pattern works well for applications that simply draw shapes or other graphical outputs to a canvas.  In this pattern, the application adds a canvas to the window and runs methods to draw on it.  For example, a simple demo application allows the user to draw filled blue ovals and red text messages at random positions on a gray canvas.  The window shown in the next screen shot places the canvas across the top row, above three command buttons labeled Draw oval, Draw text, and Clear all.  The last button deletes and erases all of the drawings on the canvas.

 

 

The next code segment shows the __init__ method for the demo program (canvasdemo1.py).  This method adds a canvas to the top row of the window.  Although the canvas technically extends beyond the window, the program gives it displayed dimensions of 400 by 200 pixels and allows the initial window to shrink-wrap around it.  The background color of the canvas is then set to gray, and the three command buttons are added.  Finally, the program creates a list to hold the IDs of the items drawn on the canvas.  These will be needed later if the user chooses to clear the canvas, alter the itemsÕ positions, and so forth. 

 

def __init__(self):

    """Sets up the window and widgets."""

    EasyFrame.__init__(self, title = "Canvas Demo 1")

 

    # Canvas

    self.canvas = self.addCanvas(row = 0, column = 0,

                                 columnspan = 3,

                                 width = 400, height = 200)

    self.canvas["background"] = "gray"

       

    # Command buttons

    self.ovalButton = self.addButton(text = "Draw oval",

                                     row = 1, column = 0,

                                     command = self.drawOval)

    self.textButton = self.addButton(text = "Draw text",

                                     row = 1, column = 1,

                                     command = self.drawText)

     

          self.clearButton = self.addButton(text = "Clear all",

                                      row = 1, column = 2,

                                      command = self.clearAll)

       

    # Holds the IDs of the items after they're drawn

    self.items = list()

 

 

The event handler methods for the command buttons run methods on the canvas to draw an oval, draw the string "Hello world!" or erase all of the items from the canvas.  The next code segment lists these three methods.

 

def drawOval(self):

    """Draws a filled oval at a random position."""

    x = random.randint(20, 350)

    y = random.randint(20, 120)

    self.items.append(self.canvas.drawOval(x, y, x + 25, y + 25,

                                           fill = "blue"))

 

def drawText(self):

    """Draws 'Hello world!' at a random position."""

    x = random.randint(20, 350)

    y = random.randint(20, 120)

    self.items.append(self.canvas.drawText("Hello world!", x, y,

                                           fill = "red"))

 

def clearAll(self):

    """Deletes all the shapes from the canvas."""

    for item in self.items:

        self.canvas.deleteItem(item)

    self.items = list()

 

 

The EasyCanvas class includes methods for drawing ovals, rectangles, line segments, text, and images.  These methods are summarized in the next table.

 

EasyCanvas Method

What it does

deleteItem(itemID)

Removes the item with the specified ID.  This ID is created and returned by the method that draws the item.

drawLine(x0, y0, x1, y1,   

         fill = "black",

         width = 1)

Draws a line segment between the specified end points, in the given color and width.

drawRect x0, y0, x1, y1,   

         outline = "black",

         fill = None)

Draws a rectangle with the given corner points, in the given outline color.  If fill is None, only the outline is drawn.

drawOval x0, y0, x1, y1,   

         outline = "black",

         fill = None)

Draws an oval within an imaginary rectangle with the given corner points, in the given outline color.  If fill is None, only the outline is drawn.

drawText(text, x, y,

         fill = "black")

Draws the text centered on the given point, in the given fill color.

drawImage(image, x, y,

         anchor = CENTER)

Draws the image (a PhotoImage), centered at the given coordinates.

 

The fill attribute of the text is its color (black by default); the fill attribute of each shape fills it with the specified color (None by default).  Ovals and rectangles also have an outline attribute, whose default value of black can be overridden. 

Several common or primary colors have string values, as the previous code segment shows.  Alternatively, a total of 224 distinct colors can be specified by using six-digit hexadecimal strings in the RGB (red/green/blue) color scheme.  For example, a shade of light gray is "#DDDDDD".   Each pair of digits, from left to right, specifies the intensity of red, green, and blue, respectively, in the color value.  The brightest intensity is FF (256), and the darkest is 00.  The reader is referred to Page TutorÕs ColorPicker site to assist with conversions between hex and all the colors.

The example program canvasdemo4.py draws an image on a canvas and allows the user to erase it and redraw it by clicking command buttons.