Description
Graphical programs are natural applications for object-oriented programming. In this lab exercise, you
will construct a number of classes to manage objects on a Polymorphism. We’ll begin by extending our
working knowledge of the Polymorphism. Recall that you can find a complete description of
the entire module on the “official” Python reference online:
http://docs.python.org/3.2/library/turtle.html
Warm-up
You already know how to draw lines and turn the turtle, but a number of other objects can be drawn using
turtle methods in one step. Circles are one example, complex polygons are another. For example, to
draw a circle at the location 40,40:
>>> myt.penup()
>>> myt.goto(40,40)
>>> myt.circle(100)
>>> myt.pendown()
>>> myt.circle(100)
Voila! We have a circle at 40,40. But it isn’t very colorful… In fact, it’s transparent. The only thing
that shows is the outline of the circle. In order to have a colored circle we have to do a few more things,
including filling it with a color. Creating a “filled” color object, requires four steps in turtle graphics:
1. Set the fill color to whatever you want (“red”, “blue”, “yellow”, etc.)
2. Indicate the start of a filled shape by invoking the .begin_fill method
3. Perform a sequence of drawing operations that will create an “enclosed” figure
4. Indicate the end of the filled shape, and fill the object with the fill color by invoking the
.end_fill method
It’s easier to do than describe! Let’s redraw our circle filled with red:
>>> myt.fillcolor(“red”)
>>> myt.begin_fill()
>>> myt.circle(100)
>>> myt.end_fill()
We now have a nice red circle. Note that the .fillcolor() method takes a string. Let’s do it again
with a rectangle. There are turtle methods for drawing polygons that you might like to explore on your
own. For now, we’ll just use the line drawing methods we’ve used in the past:
>>> myt.penup()
>>> myt.goto(-50,-50)
>>> myt.pendown()
>>> myt.fillcolor(“blue”)
>>> myt.begin_fill()
>>> for i in range(4):
myt.forward(100)
myt.right(90)
>>> myt.end_fill()
Functions are Objects!
Yes, it’s true. Function names in Python are object references (just like variables!) and can be used in
lists, dictionaries and even as arguments in other functions. In order to obtain graphical style (i.e.
“mouse”) input in our programs, we need to exploit this capability by providing a function that will be
called when a mouse “click” occurs.
Mouse tracking and input (“clicking” a mouse button) are handled asynchronously to your program’s
operation. When the user “clicks” a mouse button, Python calls a function that you supply and passes the
x and y coordinates of the mouse location as they were when the button was pressed. Turtle graphics
“knows” what function to call because you “tell” it by giving the name of the function to a screen method,
.onclick(function_name). Again, it’s probably easier to demonstrate than describe. First, write a
short function definition:
>>> def mouseInput(x,y):
print(x,’,’,y)
Our mouseInput function will be called anytime the mouse button is “clicked” by the user. Note that it
must have two arguments for the x and y coordinates of the mouse location corresponding to the button
press (NOTE: if this is a class member function, you will also need to supply the “self” argument as
always). In this case, our “button handler” function simply prints out the x and y coordinate values on the
terminal.
Next, we have to instruct the turtle Screen object that the mouseInput() function is the one that should
be called when the mouse button is clicked. We do that by registering the function using the screen
method: .onclick(function_name)
>>> scr = myt.getscreen() #get the Screen object for myt
>>> scr.onclick(mouseInput) #register the button handler function
Note that the single argument to the .onclick() method is the name of the function that we’ve written.
.onclick just “sets up” the mechanism… we have to do one more thing to actually make Python start
processing button presses. It involves one more screen method that takes no arguments:
>>> scr.listen()
Position the turtle window and the python shell so that you can see both. Now move the mouse around in
the turtle window and press the left button on the mouse and watch the output in the python shell display.
You should see x and y values printed each time you press the button.
You are now ready to construct more sophisticated graphics programs. Let’s use objects and inheritance
to do something fun.
Stretch
1). Shape Class
Construct a base class named Shape that will maintain common “shape” information such as location,
fill color, etc. The shape class should have instance variables for the x and y location of the shape (type
int), the fill color (type str) and a boolean indicating if the shape should be filled or not. The
location should default to 0,0. The fill color should default to a Null string, and filled should default to
False. Provide the following Shape methods:
• setFillcolor(str) Mutator to set the fill color to the value of the string argument
• setFilled(bool) Mutator to set the filled boolean to the value of the boolean argument
• isFilled() Accessor that will return the value of the filled instance variable
2). Circle Class
Now, create a new class named Circle that inherits the Shape base class. The constructor for the
Circle class should have arguments for the x and y location (default to zero) and the radius of the circle
(default to 1). Be sure to properly call the super-class constructor! Provide the following Circle
methods:
• draw(turtle) An accessor method that will draw a circle using turtle graphics. draw()
will take a single turtle object as an argument and draw the circle at its specified x,y location. If
the circle is “filled”, be sure to implement the proper sequence of operations to draw a filled circle
of the appropriate color. Otherwise draw an unfilled circle.
Test your two class definitions by creating and drawing several circles
3). Graphics Display Object
Create another class named Display that will maintain a graphics environment involving shapes and
mouse input. The constructor for the Display class will instantiate a number of instance variables and
set up the turtle environment to enable the input of mouse button selection events. Be sure to import the
turtle module in your class definition file.
The Display constructor should do the following:
• Initialize a Turtle instance variable using the Turtle() method
• Initialize a Screen object member using the Turtle .getscreen() method
• Initialize an instance variable named elements (a null list)
• Set the speed and delay of the turtle and screen to zero and hide the turtle
Create a Display method named mouseEvent(x,y) that will process mouse button presses. For
this version of the program, the mouseEvent() method will do the following:
• Create and draw a circle object at the x,y location indicated by the mouse press (passed as
arguments to the function). The circle should be filled and have a random radius between 10
and 100. It should also have a random color. (consider using a list of color strings that you can
use the random.shuffle() method on, then simply pick the first from the shuffled list!)
You will also need to add statements to the Display constructor to register the mouseEvent()
method as the “on-click” routine (don’t forget to enable it using the listen() screen method!)
If you’ve done this correctly, you should be able to simply instantiate a Display object, then use your
cursor to roam about the window. Each time you press the mouse button, a randomly sized/colored circle
should appear at the mouse location.
Workout
1). Adding and Removing Shapes
The Display class has an instance variable named elements that was initialized as a null list. The
elements list will be used to keep track of shapes that are currently being displayed. Add the
following mutator methods to the Display class:
add(shape) : Takes a shape object as an argument and adds it to the end of the elements list.
After the shape has been added, it should be drawn on the display using the object’s draw method.
remove(shape) : Takes a shape object as an argument and removes it from the elements list.
After the shape has been removed from the list, clear the display (using the appropriate Turtle
method), then redraw each shape in the elements list. The shapes should be drawn in order of
appearance in the list.
Be sure to test each of these new methods using Python in interactive mode. Add a few circles, then
remove them.
2). Rectangle Class
Add another geometric shape class to draw rectangles. The Rectangle class should also be derived
from the Shape base class. The constructor should have arguments for the x and y location, plus the
width and height of the rectangle object. Also include a draw method that will draw a rectangle based on
its x, y, width, height, filled and fillColor attributes (refer to the Circle class).
Test your new class by using the add and remove methods in the Display object to display and remove
a few rectangle objects.
3). Selecting Objects
Add a method to both the circle and rectangle classes named isIN that will take x,y coordinate
values and return True if the point x,y is within the boundaries of the object.
[ Hint: The “location” coordinates of the object reflect where it was drawn. For a circle, this is the
bottom-center point of the circle ]
4). Displaying and Removing Shapes
Modify the mouseEvent handler function in the Display class to remove a shape if the mouse button
is pressed while the pointer is “inside” a currently displayed shape. If it’s not inside any displayed object,
construct and display either a randomly sized/colored circle or a randomly sized/colored rectangle per the
instructions in Stretch problem 3.
Test your program by creating and removing objects from the display using the mouse.
Challenge
Add a Button class that is a child of a rectangle and adds both a label (string) and a button handler
(function reference). Either bind the handler function to the object using the constructor or a mutator
method (or both!)
Now create a button-handler function to toggle a state variable (in the Display class) that will direct the
construction of rectangles or circles. In other words, choose which type of shape to draw based on the
state variable rather than a “flip of the coin”.
Modify the mouseEvent handler in the Display class to recognize a button-press and call the bound
handler function. Finally, construct and add a Button to the display.
Congratulations! You’ve created a fairly sophisticated graphics program using the simplest of all graphics
interfaces: turtle graphics.
Use your imagination and modify the program to do something creative and interesting!