Drawing is cool!

Drawing pictures with turtle graphics can illustrate important computer science concepts while being fun as well.

This series of lessons shows students how to create a drawing program that draws pictures with color, different line characteristics, and shapes. It also will show students how to save and reload a picture in their program.

 

Drawing is Cool!

Drawing pictures can be a lot of fun. In this series of lessons, you learn how to draw pictures on the screen using turtle graphics. Check out this picture. There isn't a lot there yet, but if you click on the image below you can see the code that was used to create this drawing program. If you copy this code and the picture of the pencil to your own computer, you can run this program to see what it does. Try it out!

There are a lot of things we can do to improve this code. Take a look at it first to see how the program works. There are comments in the code to help you understand what is going on.

We'll start from the top of the file and cover the code in the order that it is executed.

When writing a program, you can't possibly write all the code yourself. Python programmers import code from other modules so they can use that code in their programs. Python comes with a large number of modules that all have documentation to describe what they do and how to use them. You import code from a module by writing import statements at the top of your program.

This program imports two modules, the tkinter and the turtle modules.

import turtle
import tkinter

The turtle module includes code that lets you draw using turtle graphics. The idea is simple, you have a turtle walking around on the beach. As the turtle moves it leaves a mark in the sand where its tail drags. The turtle can pick up its tail or it can leave its tail down.

Writing def main(): causes Python to define a function. A function in Python is like a function in Mathematics. You can define it and once you have defined it you can call it. The main function that is defined in this program does not have any parameters. We'll talk more about this soon. The code at the end of the program calls the main function.

if __name__ == "__main__":
   main()

This code is what is called an "if" statement. If the condition __name__ == "__main__" is True, then Python will call the main function. That means the main function will be executed from top to bottom starting with line number 12 in the program (i.e. the line root = tkinter.Tk()).

The line of code root = tkinter.Tk() creates a window on your computer screen. Initially, the window is empty and is very uninteresting. You fill a window with widgets to make it into an interesting application. We're writing a drawing application so we'll begin by setting the title of the application. The variable root represents the main window in our application. We can set the title of the main window by sending a message to the root window with the line of code

   root.title("Draw!")

This is object-oriented programming. The root variable represents the main window of our application and we can communicate with the window object by sending it messages, like the title message. Sometimes we say we are invoking the title method on the root object. Invoking a method and sending a message are two ways of saying the same thing.

The lines

   cv = tkinter.Canvas(root,width=600,height=600)
   cv.pack(side = tkinter.LEFT)

create a Canvas widget and place it on the left side of the root window. A canvas widget is an area where you can draw things with a turtle object. Our canvas widget will be called cv in our program.

These two lines of code

   t = turtle.RawTurtle(cv)
   screen = t.getscreen()

create a turtle object, called t, and send a message to the turtle object to get the screen object (which is just another representation of the canvas, cv. Once we have the screen, we can send it a message to tell the screen to display the turtle as a pencil. That's what these lines of code do.

   screen.register_shape("pencil.gif")
   t.shape("pencil.gif")

Creating an entry field to enter the width of the line that is drawn is pretty simple. An entry widget is created. The entry widget has a StringVar object associated with it. A StringVar object has to messages it understands, get and set. The set method sets a value in the entry widget. The code below sets the string "1" in the entry widget. The get message is used later on.

   pointLabel = tkinter.Label(frame,text="Width")
   pointLabel.pack()
 
   pointSize = tkinter.StringVar()
   pointEntry = tkinter.Entry(frame,textvariable=pointSize)
   pointEntry.pack()
   pointSize.set(str(1))

When a button is added to a Tkinter application, you create the button, add it to the window, and then associate the button with a function that is called when the button is pressed. The code below creates the quit button and then ties it to the quitHandler function.

   def quitHandler():
root.destroy()
root.quit()
quitButton = \ tkinter.Button(frame, text = "Quit", command=quitHandler)
quitButton.pack()

When a mouse click occurs, we want the turtle to draw a line to that place on the screen where you clicked. To do that we must create an event handler to handle mouse click events. That's what this code does for us. Notice that it sends the get message to the pointSize StringVar object to get its value. It converts this value to an integer and uses that as the width of the line to draw when moving the turtle.

   def clickHandler(x,y): 
      t.width(int(pointSize.get()))
      t.goto(x,y)
 
   screen.onclick(clickHandler)

Finally, the last line of code in the main function tells the Tkinter code to call the mainloop function. This mainloop function processes the events that occur (like button presses and mouse clicks) by calling the appropriate event handler to process the event.

   tkinter.mainloop()
     

Now You Try It

There are two things we'll try today. First, we'll create an entry field so we can set the color of the lines we draw. To do this we'll create a new entry field and a StringVar to go with it. The code looks like this. You can write this code after the code that creates the pointSize StringVar and pointEntry Entry widget. Be sure to indent your code the same amount as the code above it. Do you understand what each line of code does? If not, ask!

   colorLabel = tkinter.Label(frame, text="Color")
   colorLabel.pack()
   colorVar = tkinter.StringVar()
   colorEntry = tkinter.Entry(frame,textvariable=colorVar)
   colorEntry.pack()
   colorVar.set("black")

This is almost all the code we need. The only extra bit of code is in the click handler. To use the current color of the colorVar StringVar object, you have to tell the turtle to use the color when drawing. You do this before you tell the turtle to goto the next point. Here is how you tell the turtle to use the colorVar's color.

   t.color(colorVar.get())

Many colors are available in turtle graphics, so don't be shy about trying a few of them. Pretty much any color can also be created by providing a color in RGB mode. In this mode, you write the red, green, and blue components in hexadecimal form. Hexadecimal is a counting system that has 16 values for each digit. The values are 0-9 and a-f. A color in RGB mode has two hexadecimal digits for each component (the red, green, and blue components). So the value

#ffff00

is a color where the red and green components are at full intensity while there is no blue component at all. In other words, the color represented above is yellow.

Have Extra Time?

Try creating a clear button that clears the screen so you can start over. To clear the screen you send a message to the turtle called clear. So you write

t.clear()

to clear the screen. To get this to work correctly, you need to follow the pattern that was used to create the quitButton and the quitHandler.

If you get stuck, ask for help!