CSC111 Lab 12 Solution Programs 2014
--D. Thiebaut (talk) 20:19, 24 April 2014 (EDT)
Contents
Solution Program for Part 1
from graphics111 import *
MAXWIDTH = 600
MAXHEIGHT = 400
class Car:
def __init__(self, x, y, w, h, color ):
self._body = Rectangle( x, y, w, h, color )
self._w1 = Wheel( x+w//4, y+h, w//4 )
self._w2 = Wheel( x+3*w//4, y+h, w//4 )
def draw( self, canvas ):
self._body.draw( canvas )
self._w1.draw( canvas )
self._w2.draw( canvas )
def move( self, canvas, dx, dy ):
self._body.move( canvas, dx, dy )
self._w1.move( canvas, dx, dy )
self._w2.move( canvas, dx, dy )
def mouseEvent( win, canvas, x, y ):
global menu, car
button = menu.buttonClicked( x, y )
if button == None:
# create a circle centered on mouse coordinates
# give it a color that depends on the location (for fun)
c1 = Circle( x, y, 20, (x%256, y%256, (x+y)%256 ) )
c1.draw( canvas )
return
if button == "LeftArrow":
#print( "left-arrow clicked!" )
car.move( canvas, -10, 0 )
return
if button == "RightArrow":
#print( "right-arrow clicked!" )
car.move( canvas, 10, 0 )
return
if button == "Minus":
print( "minus clicked!" )
return
if button == "Plus":
print( "plus clicked!" )
return
def main():
global menu, car
win = GraphicsWindow(MAXWIDTH, MAXHEIGHT)
canvas = win.canvas()
canvas.setCallbackFunction( mouseEvent )
menu = Menu()
menu.draw( canvas )
car = Car( 100, 100, 50, 20, (250, 250, 0) )
car.draw( canvas )
win.wait()
win.close()
main()
Solution Programs for Part 2
Creating the Map
This is definitely more involved than what you had to do, but contains all the elements you had to put together. This program is part of Homework #12.
# MapDigitizer.py
# D. Thiebaut
#
# This program imports the file SmithMapSmall.gif and displays it on the canvas.
# The user then must use the + symbol in the menu to start the digitization, which
# first asks the user to enter the name of the building. The user then clicks on vertices
# of the building's outline to record their coordinates. When the user has gone around the
# full building, she clicks on the minus symbol of the menu. The program then writes the
# csv representation of the building to a file called buildings.csv.
#
from graphics111 import *
MAXWIDTH = 700 # the dimensions of the gif image
MAXHEIGHT = 836
## call-back function.
# mouseEvent(): called by the graphics library whenever
# a mouse event is captured.
# win: a reference to the main graphics window
# canvas: a reference to the canvas
# x, y: the coordinates (in pixels) of the mouse click.
# (the top-left corner is 0,0)
def mouseEvent( win, canvas, x, y ):
# global variables shared with main()
global menu # the menu top-left of the canvas
global buildingList # list of building coordinates
global csvFileName # name of the file where building csv info stored
# ask menu is mouse was clicked on one of its buttons
button = menu.buttonClicked( x, y )
# mouse not clicked on menu item. Add x, y coords to the
# current building list.
if button == None:
buildingList.append( x )
buildingList.append( y )
# show some fun feedback for user
if len( buildingList ) >=7 :
canvas.setColor( 200, 130, 199 )
canvas.drawPolygon( buildingList[1:] )
return
# nothing to do for left or right arrow
if button == "LeftArrow" or button == "RightArrow":
return
# if plus button clicked, start a new list for a new
# building. Get a new name and start the list.
if button == "Plus":
rawName = input( "Building name? " ).strip()
# capitalize the name
name = ""
for word in rawName.strip().split():
name += word.capitalize()+ " "
# start new list
buildingList = [ name.strip() ]
return
# if minus button, transform the list into csv line and
# append to file.
if button == "Minus":
for i in range( 1, len( buildingList ) ):
buildingList[i] = str( buildingList[i] )
file = open( csvFileName, "a" )
file.write( ", ".join( buildingList ) + "\n" )
file.close()
return
# ========================================================
# Main Program
# Declares globals shared with call-back function
# Creates a window and gets access to its canvas
# Displays a map on the canvas
# Draws a menu in top left corner
# Waits for for mouse events.
# ========================================================
def main():
# list of variables shared with the call-back function
global menu
global buildingList
global csvFileName
# the two files (located in same directory).
# gif contains map, csv contains output of program
csvFileName = "buildings.csv"
gifFileName = "SmithMapSmall.gif"
# open the window and get access to its canvas
win = GraphicsWindow(MAXWIDTH, MAXHEIGHT)
canvas = win.canvas()
canvas.setCallbackFunction( mouseEvent )
# put gif image on canvas
photo = tk.PhotoImage( file=gifFileName )
canvas._tkcanvas.create_image(0,0, image=photo, anchor = tk.NW )
# add a menu to the window
menu = Menu()
menu.draw( canvas )
# wait and respond to events, or comment out and make the program
# stop as soon as car disappears.
win.wait()
win.close()
main()
Reading and Drawing the Digitized Map
from graphics111 import *
MAXWIDTH = 800
MAXHEIGHT = 800
def main():
win = GraphicsWindow(MAXWIDTH, MAXHEIGHT)
canvas = win.canvas()
file = open( "smithMap.csv", "r" )
for line in file:
name = line.split( "," )[0].strip()
coords = line.split( "," )[1:]
for i in range( len( coords ) ):
coords[i] = int( coords[i].strip() )
p = Polygon( coords, (250, 250, 10 ) )
p.draw( canvas )
canvas.drawText( coords[0], coords[1], name )
file.close()
win.wait()
win.close()
main()
And if you are interested in a tightly packed program, barely readable, but spanning very few lines, here's the minimalist version:
from graphics111 import *
MAXWIDTH = 800
MAXHEIGHT = 800
def main():
win = GraphicsWindow(MAXWIDTH, MAXHEIGHT)
canvas = win.canvas()
for line in open( "smithMap.csv", "r" ):
Polygon( [int(k) for k in line.split( "," )[1:] ], (250, 250, 10 ) ).draw( canvas )
canvas.drawText( int( line.split( "," )[1] ),
int( line.split( "," )[2] ),
line.split( "," )[0].strip() )
win.wait()
win.close()
main()