- Vocabulary
By the end of this note, you need to understand these terms,
and in the case of specific methods,
you need to know how and why to implement them.
- struct, class, object, instance
- attribute, method, constructor
- __init__
Note that this is a subset of material from previous semesters.
In particular, the following may be covered next week, or in some
cases not at all this semester:
- subclass, superclass, super, inherit, override
- static method, @staticmethod, class method, @classmethod
- type, isinstance
- __str__, __repr__, __eq__, __hash__
- __ne__, __add__, __radd__, __gt__, __ge__, __lt__, __le__, etc..
- __dict__
- Structs (download
structClass.py)
# Here we use 'struct' in the classic sense:
# https://en.wikipedia.org/wiki/Struct_(C_programming_language)
# Note that this is not the same as Python's struct module:
# https://docs.python.org/3/library/struct.html
# Also note: you are not responsible this week for the Struct implementation.
# That is, you do not need to know how to write the Struct class, but
# rather only how to use it.
from structClass import Struct # (downloaded in structClass.py, see link above)
obj = Struct()
obj.x = 42
print("obj.x = ", obj.x)
- Example: dotsDemo
######################################################
# Struct Example: dotsDemo
######################################################
import random
from structClass import Struct # defined above (saved in structClass.py)
from tkinter import *
class Dot(Struct): pass
def init(data):
data.dots = [ ]
def dotContainsPoint(dot, x, y):
d = ((dot.x - x)**2 + (dot.y - y)**2)**0.5
return (d <= dot.r)
def mousePressed(event, data):
for dot in reversed(data.dots):
if (dotContainsPoint(dot, event.x, event.y)):
dot.clickCount += 1
return
radius = random.randint(20,50)
color = random.choice(["pink","orange","yellow","green","cyan","purple"])
data.dots.append(Dot(x=event.x, y=event.y, r=radius,
fill=color, clickCount=0))
def redrawAll(canvas, data):
for dot in data.dots:
canvas.create_oval(dot.x-dot.r, dot.y-dot.r,
dot.x+dot.r, dot.y+dot.r,
fill=dot.fill)
canvas.create_text(dot.x, dot.y, text=str(dot.clickCount))
def keyPressed(event, data):
pass
def timerFired(data):
pass
####################################
# use the run function as-is
####################################
def run(width=300, height=300):
def redrawAllWrapper(canvas, data):
canvas.delete(ALL)
redrawAll(canvas, data)
canvas.update()
def mousePressedWrapper(event, canvas, data):
mousePressed(event, data)
redrawAllWrapper(canvas, data)
def keyPressedWrapper(event, canvas, data):
keyPressed(event, data)
redrawAllWrapper(canvas, data)
def timerFiredWrapper(canvas, data):
timerFired(data)
redrawAllWrapper(canvas, data)
# pause, then call timerFired again
canvas.after(data.timerDelay, timerFiredWrapper, canvas, data)
# Set up data and call init
class Struct(object): pass
data = Struct()
data.width = width
data.height = height
data.timerDelay = 100 # milliseconds
init(data)
# create the root and the canvas
root = Tk()
canvas = Canvas(root, width=data.width, height=data.height)
canvas.pack()
# set up events
root.bind("<Button-1>", lambda event:
mousePressedWrapper(event, canvas, data))
root.bind("<Key>", lambda event:
keyPressedWrapper(event, canvas, data))
timerFiredWrapper(canvas, data)
# and launch the app
root.mainloop() # blocks until window is closed
print("bye!")
run(400, 200)
- Example: betterDotsDemo
######################################################
# Struct-Free Example: betterDotsDemo
######################################################
import random
from tkinter import *
class Dot(object):
def __init__(self, x, y):
self.x = x
self.y = y
self.r = random.randint(20,50)
self.fill = random.choice(["pink","orange","yellow","green",
"cyan","purple"])
self.clickCount = 0
def containsPoint(self, x, y):
d = ((self.x - x)**2 + (self.y - y)**2)**0.5
return (d <= self.r)
def draw(self, canvas):
canvas.create_oval(self.x-self.r, self.y-self.r,
self.x+self.r, self.y+self.r,
fill=self.fill)
canvas.create_text(self.x, self.y, text=str(self.clickCount))
def init(data):
data.dots = [ ]
def mousePressed(event, data):
for dot in reversed(data.dots):
if (dot.containsPoint(event.x, event.y)):
dot.clickCount += 1
return
data.dots.append(Dot(event.x, event.y))
def redrawAll(canvas, data):
for dot in data.dots:
dot.draw(canvas)
def keyPressed(event, data):
pass
def timerFired(data):
pass
####################################
# use the run function as-is
####################################
def run(width=300, height=300):
def redrawAllWrapper(canvas, data):
canvas.delete(ALL)
redrawAll(canvas, data)
canvas.update()
def mousePressedWrapper(event, canvas, data):
mousePressed(event, data)
redrawAllWrapper(canvas, data)
def keyPressedWrapper(event, canvas, data):
keyPressed(event, data)
redrawAllWrapper(canvas, data)
def timerFiredWrapper(canvas, data):
timerFired(data)
redrawAllWrapper(canvas, data)
# pause, then call timerFired again
canvas.after(data.timerDelay, timerFiredWrapper, canvas, data)
# Set up data and call init
class Struct(object): pass
data = Struct()
data.width = width
data.height = height
data.timerDelay = 100 # milliseconds
init(data)
# create the root and the canvas
root = Tk()
canvas = Canvas(root, width=data.width, height=data.height)
canvas.pack()
# set up events
root.bind("<Button-1>", lambda event:
mousePressedWrapper(event, canvas, data))
root.bind("<Key>", lambda event:
keyPressedWrapper(event, canvas, data))
timerFiredWrapper(canvas, data)
# and launch the app
root.mainloop() # blocks until window is closed
print("bye!")
run(400, 200)
- Example: smileyClassDemo
######################################################
# smileyClassDemo (similar to betterDotsDemo but more fun!)
######################################################
import random
from tkinter import *
class Smiley(object):
def __init__(self, x, y):
self.x = x
self.y = y
self.r = random.randint(50,100)
self.color = random.choice(["cyan", "yellow", "lightGreen", "pink",
"orange", "green", "lightBlue", "purple"])
self.maxSmileyPoints = 100
self.smileyPoints = self.maxSmileyPoints # the more points the happier
def draw(self, canvas):
(x, y, r) = (self.x, self.y, self.r)
# face
canvas.create_oval(x-r, y-r, x+r, y+r,
fill=self.color, outline="black", width=4)
# eyes
eyeY = y-r/3
eyeR = r/6
for eyeX in [x-r/3, x+r/3]:
canvas.create_oval(eyeX-eyeR, eyeY-eyeR, eyeX+eyeR, eyeY+eyeR,
fill="black")
# mouth
mouthY1 = y+r/3
mouthDy = r/6 # max height of mouth smile
halfMax = self.maxSmileyPoints/2
mouthY0 = mouthY1 - mouthDy*(self.smileyPoints - halfMax)/halfMax
mouthY2 = mouthY0
mouthDx = r*2/3
for mouthX0 in [x-mouthDx, x+mouthDx]:
canvas.create_line(mouthX0, mouthY0, x, mouthY1,
fill="black", width=4)
def contains(self, x, y):
return ((self.x - x)**2 + (self.y - y)**2 <= self.r**2)
def init(data):
data.timerDelay = 100
data.smileys = [ ]
def mousePressed(event, data):
for smiley in reversed(data.smileys):
if (smiley.contains(event.x, event.y)):
smiley.smileyPoints = smiley.maxSmileyPoints
return
# clicked outside of all smileys, so make a new smiley
newSmiley = Smiley(event.x, event.y)
data.smileys.append(newSmiley)
def drawSmileys(canvas, data):
for smiley in data.smileys:
smiley.draw(canvas)
def drawText(canvas, data):
texts = ["Smile!!!",
"Click in Smileys to make them Smile!",
"Click outside Smileys to make a new Smiley!"
]
font = "Arial 20 bold"
x = data.width/2
for i in range(len(texts)):
y = 25*(i+1)
canvas.create_text(x, y, text=texts[i], font=font)
def redrawAll(canvas, data):
drawSmileys(canvas, data)
drawText(canvas, data)
def keyPressed(event, data):
pass
def timerFired(data):
for smiley in data.smileys:
if (smiley.smileyPoints > 0):
smiley.smileyPoints -= 1
####################################
# use the run function as-is
####################################
def run(width=300, height=300):
def redrawAllWrapper(canvas, data):
canvas.delete(ALL)
redrawAll(canvas, data)
canvas.update()
def mousePressedWrapper(event, canvas, data):
mousePressed(event, data)
redrawAllWrapper(canvas, data)
def keyPressedWrapper(event, canvas, data):
keyPressed(event, data)
redrawAllWrapper(canvas, data)
def timerFiredWrapper(canvas, data):
timerFired(data)
redrawAllWrapper(canvas, data)
# pause, then call timerFired again
canvas.after(data.timerDelay, timerFiredWrapper, canvas, data)
# Set up data and call init
class Struct(object): pass
data = Struct()
data.width = width
data.height = height
data.timerDelay = 100 # milliseconds
init(data)
# create the root and the canvas
root = Tk()
canvas = Canvas(root, width=data.width, height=data.height)
canvas.pack()
# set up events
root.bind("<Button-1>", lambda event:
mousePressedWrapper(event, canvas, data))
root.bind("<Key>", lambda event:
keyPressedWrapper(event, canvas, data))
timerFiredWrapper(canvas, data)
# and launch the app
root.mainloop() # blocks until window is closed
print("bye!")
run(800, 600)