Lab: Drawing Lines in TKinter, part 1

Goal

After doing this lab, you’ll be able to

·      Create a simple tkinter Canvas object

·      Interact with the Canvas using mouse events,

·      Draw simple objects

Background

So far we have only used TKinter to create simple user interfaces. This time we will use it as a drawing canvas. In this lab we will simply draw; in future labs we will be able to select parts of our drawings and analyze them.

Procedures

1.  Start Idle. When your Python shell opens, click File…New. In the Untitled window, click File…Save As, navigate to the folder you are using for your Python modules, and use DrawLines.py as your file name. Click Save.

Add the following code:

import tkinter as tk
root
 
tk.Tk()

root.title('Draw Lines')

root.mainloop()

2.  Run the program (F5 on a PC, fn-F5 on a Mac, or Run…Run Module everywhere). You should see a small window pop up with Draw Lines in the title bar.

3.  After the line of code that sets the title for the root frame, add the following line of code:

WIDTH = 800
HEIGHT = 400
w = tk.Canvas(root, width=WIDTH, height=HEIGHT)

WIDTH and HEIGHT are 2 variables that we are using as constants to define the size of the surface (in pixels) that we want to draw on. The statement

    
w = tk.Canvas(root, width=WIDTH, height=HEIGHT

creates a
Canvas widget, attaches it to the root frame, and sets its width and height to 800 and 400 pixels respectively.

4.  Run your code again.

a.  Do you see any changes from the last run?

5.  Now add the following line of code:

w.pack()

Run your code again

a.  What change do you see from the previous run? The pack() function is another, simpler layout manager than grid(), the one we used in the last lab. It simply lays out one widget after another on the frame. In this lab, our Canvas widget is the only one. You will not see widgets appear in a frame until you add them with a layout function.

6.  Let’s make sure the Canvas widget is working. Add the following line of code below w.pack():

w.create_line(0, 0, 300, 300)

If you don’t see a diagonal line or if you get errors, make sure that you typed this line in exactly as written and run it again. When you are satisfied, comment out this line.

7.  Now you can make your program respond to mouse events. For this first program, we will only recognize a mouse left-button click. In TKinter, the left mouse button is treated as button 1 and the right as button 2. It is very easy to make this work. First, add the following line of code after the line for w.pack():

w.bind('<Button-1>', draw)

This says that when the left-mouse button is pushed (
Button-1), call the draw() function. We will define this function in just a moment. Although your draw() function definition will look just like other functions, it is called by the event handling loop ( mainloop() ) when the operating system (Windows, Mac OS X, or whatever system you’re running your program on) tells your program that a user clicked the left-mouse button while the mouse cursor was within its frame. This is called a ‘callback’ function. This is how most modern GUIs allow a program to interact with events.

8.  Create the draw() function definition like the definition you created in step 10 of lab 4. In other words, your function definitions will always follow this pattern:

def functionName (parameters):

In your case,
functionName will be draw and you will have just one parameter, event. It would be best to place the definition right after the import line at the top of your program.

For now, just add the following line of code to your function, indented one tab stop:

    
print('got a left-mouse click')

9.  Run your program and click the left mouse button anywhere in the frame (except the title bar or frame edges). Make sure that you see ‘got a left-mouse click’ in the console. If not, check your work for steps 7 and 8.

10.       Add the following line of code after your print() statement (make sure you type it in as a single line of code):

w.create_oval(event.x, event.y, event.x+25, event.y+25, outline="#000000", fill="#ff0000", width=1)

So what does this do?
create_oval() is the TKinter function for creating elliptical shapes. The first 2 parameters are the x and y coordinates of the upper-left corner of the bounding rectangle surrounding the shape. These are given to you courtesy of the event loop which got the coordinates from the operating system. The next 2 arguments are the width and height of the bounding box. If they are the same value, you get a circle; if not, you get an ellipse. The fifth and sixth parameters are the outline (or stroke) color (black) and the fill color (red) using hexadecimal numbers. The last parameter is the stroke linewidth.

11.       Run your program and left-click to your heart’s content. Your page will be covered with 25-pixel diameter measles!


COMING NEXT IN PART 2: Working with global variables to make your red dots the endpoints of line segments… For now there is nothing to hand in, just have this code working by the due date (on the course schedule page).