题目
1、修改本实例程序,添加让雪人整体移动的功能。
2、修改本程序,添加修改雪人帽子和纽扣颜色的功能
答案
class Shape:
def __init__(self, cvns, points):
self.cvns = cvns
self.points = points
self.pid = None
def delete(self):
if self.pid:
self.cvns.delete(self.pid)
class ShapeAngles(Shape):
def __init__(self, cvns, points, angles=(10, 170)): # ShapeAngles类只比Shape类多出一个angles属性
super().__init__(cvns, points)
self.angles = {"start": angles[0], "extent": angles[1]}
class HatTop(Shape):
def draw(self):
self.pid = self.cvns.create_oval(*self.points) # *代表self.points为元组数据
def move(self):
self.cvns.move(self.pid, 10, 0) # 每次点击向右移动10单位
def changeColor(self): # 将颜色变为蓝色
self.delete()
self.pid = self.cvns.create_oval(*self.points, fill="blue")
class HatBottom(Shape):
def draw(self):
self.pid = self.cvns.create_polygon(*self.points)
def move(self):
self.cvns.move(self.pid, 10, 0) # 每次点击向右移动10单位
def changeColor(self): # 将颜色变为蓝色
self.delete()
self.pid = self.cvns.create_polygon(*self.points, fill="blue")
class Hat:
def __init__(self, cvns, start_point, w, h):
self.cvns = cvns
self.start_point = start_point
self.w = w
self.h = h
self.ht = HatTop(self.cvns, self.ht_cacu())
self.hb = HatBottom(self.cvns, self.hb_cacu())
def draw(self):
self.ht.draw()
self.hb.draw()
def delete(self):
self.ht.delete()
self.hb.delete()
def ht_cacu(self):
r = self.h / 3 / 2 # 帽子顶端圆的半径,圆的直径与三角形的高之比为1:2。
x1 = self.start_point[0] + self.w / 2 - r # (x1,y1)和(x2,y2)是圆的外切正方形的两个端点(西北点和东南点)
y1 = self.start_point[1]
x2 = x1 + 2 * r
y2 = y1 + 2 * r
return x1, y1, x2, y2
def hb_cacu(self):
x1 = self.start_point[0] + self.w / 2 # (x1,y1)为三角形上顶点
y1 = self.start_point[1] + self.h / 3
x2 = self.start_point[0] + self.w / 3 # (x2,y2)为三角形左顶点
y2 = self.start_point[1] + self.h
x3 = self.start_point[0] + self.w / 3 * 2 # (x3,y3)为三角形右顶点
y3 = y2
return x1, y1, x2, y2, x3, y3
def move(self):
self.ht.move()
self.hb.move()
def changeColor(self):
self.ht.changeColor()
self.hb.changeColor()
class Sense(ShapeAngles):
def draw(self):
self.pid = self.cvns.create_arc(*self.points, **self.angles) # **代表self.angles为字典类型数据
def move(self): # 每次点击向右移动10单位
self.cvns.move(self.pid, 10, 0)
class Face(HatTop):
pass
class Head:
def __init__(self, cvns, start_point, w, h):
self.cvns = cvns
self.start_point = start_point
self.w = w
self.h = h
eye0_points = self.eye0_cacu()
dx = self.h / 3 + self.h / 9
eye1_points = (eye0_points[0] + dx, eye0_points[1], \
eye0_points[2] + dx, eye0_points[3])
self.face = Face(self.cvns, self.face_cacu())
self.eye0 = Sense(self.cvns, eye0_points)
self.eye1 = Sense(self.cvns, eye1_points)
self.mouth = Sense(self.cvns, self.mouth_cacu(), (-10, -170))
def draw(self):
self.face.draw()
self.eye0.draw()
self.eye1.draw()
self.mouth.draw()
def face_cacu(self):
x1 = self.start_point[0] + (self.w - self.h) / 2 # (x1,y1)为脸圆形的外切正方形的西北点
y1 = self.start_point[1]
x2 = x1 + self.h # (x2,y2)为脸圆形的外切正方形的东南点
y2 = y1 + self.h
return x1, y1, x2, y2
def eye0_cacu(self):
left_point = (self.start_point[0] + (self.w - self.h) / 2, self.start_point[1]) # 脸圆形的外切正方形的西北点
x1 = left_point[0] + self.h / 6 # (x1,y1)为眼圆形(弧形为部分圆形)的外切正方形的西北点
y1 = left_point[1] +self.h / 3
x2 = x1 + self.h / 3 # (x2,y2)为眼圆形的外切正方形的东南点
y2 = left_point[1] + self.h / 2
return x1, y1, x2, y2
def mouth_cacu(self):
left_point = (self.start_point[0] + (self.w - self.h) / 2, self.start_point[1]) # 脸圆形的外切正方形的西北点
x1 = left_point[0] + self.h / 3 # (x1,y1)为嘴圆形(弧形为部分圆形)的外切正方形的西北点
y1 = left_point[1] + 2 * self.h / 3
x2 = x1 + self.h / 3 # (x2,y2)为嘴圆形(弧形为部分圆形)的外切正方形的东南点
y2 = y1 + self.h / 3 / 2
return x1, y1, x2, y2
def move(self):
self.face.move()
self.eye1.move()
self.eye0.move()
self.mouth.move()
class BodyOutline(HatTop):
pass
class Button(HatTop):
pass
class Body:
def __init__(self, cvns, start_point, w, h):
self.cvns = cvns
self.start_point = start_point
self.w = w
self.h = h
self._button_size = 10 # 纽扣圆的半径
self.buttons = []
self.bo = BodyOutline(self.cvns, self.body_cacu())
for pnts in self.all_button_points():
self.buttons.append(Button(self.cvns, pnts))
def draw(self):
self.bo.draw()
for bttn in self.buttons:
bttn.draw()
def body_cacu(self):
x1, y1 =self.start_point # (x1,y1)为身体圆形的西北点
x2 = x1 + self.w # (x2,y2)为身体圆形的东南点
y2 = y1 + self.h
return x1, y1, x2, y2
def button0_cacu(self):
x1 = self.start_point[0] + self.w / 2 - self._button_size # (x1,y1)为第一个纽扣圆的西北点
y1 = self.start_point[1] + self.h / 5 - self._button_size
x2 = x1 + 2 * self._button_size # (x2,y2)为第一个纽扣圆的东南点
y2 = y1 + 2 * self._button_size
return x1, y1, x2, y2
def move_dy(self, points, size):
y1 = points[1] + size
y2 = points[3] + size
return points[0], y1, points[2], y2
def all_button_points(self):
b0_points = self.button0_cacu()
size = self.h / 5
points = []
for i in range(4):
points.append(self.move_dy(b0_points, i * size))
return points
def set_button_size(self, size):
self._button_size = size
def move(self):
self.bo.move()
for bttn in self.buttons:
bttn.move()
def changeColor(self):
for bttn in self.buttons:
bttn.changeColor()
class Snow:
def __init__(self, cvns, points, w=150, h=450):
self.cvns = cvns
self.points = points
self.w = w
self.h = h
self.hat = Hat(self.cvns, self.points, self.w, self.h / 6)
self.head = Head(self.cvns, (self.points[0], self.points[1] + self.h / 6), self.w, self.h / 3) # self.h / 3?
self.body = Body(self.cvns, (self.points[0], self.points[1] + self.h / 2), self.w, self.h / 2)
def draw(self):
self.hat.draw()
self.head.draw()
self.body.draw()
def move(self):
self.hat.move()
self.head.move()
self.body.move()
def changeColor(self):
self.hat.changeColor()
self.body.changeColor()
测试
if __name__ == "__main__":
import tkinter
root = tkinter.Tk()
cvns = tkinter.Canvas(root, width=600, height=550, bg="white")
cvns.pack()
snow = Snow(cvns, (10, 5), 200, 450) # 让雪人缩小一点
snow.draw()
def snow_move(): # 定义一个移动函数,将其作为command的实参
snow.move()
def change_color(): # 定义一个变颜色函数,将其作为command的实参
snow.changeColor()
frm = tkinter.Frame(root)
frm.pack()
sub_frm = tkinter.Frame(frm)
sub_frm.pack(side="bottom")
Butt1 = tkinter.Button(sub_frm, text="move", command=snow_move).grid(row=0, column=0)
Butt2 = tkinter.Button(sub_frm, text="change color", command=change_color).grid(row=0, column=1)
root.mainloop()