Python tkinter Canvas root.after()超出了最大递归深度

Ras*_*vić 1 python canvas tkinter tkinter-canvas

    from tkinter import *
    root = Tk()
    canvas = Canvas(root, width=400, height= 400, bg="white")
    canvas.pack()
    rect = canvas.create_rectangle(100, 100, 110, 110, fill='blue')
    def move_down(event):
        canvas.move(rect, 0, 10)
        root.after(1,move_down(event))
    root.bind('', move_down)
    root.mainloop()

我似乎无法弄清楚如何root.after()的工作原理.我如何解决这个问题,以便矩形继续向下移动?

Kev*_*vin 8

简短版本:您不能将括号放在传递给的函数上after.

    root.after(1,move_down(event))
Run Code Online (Sandbox Code Playgroud)

该行不会将该函数注册move_downafter事件的回调.相反,它会move_down立即move_down调用,如果没有输入无限递归,则会将返回值注册为回调.

要解决这个问题,请在move_down不实际调用它的情况下使用,并创建event一个可选变量,因为after它不会提供值.你可能也应该使用大于1毫秒的时间,否则你的矩形会在眨眼间拉开屏幕.

from tkinter import *
root = Tk()
canvas = Canvas(root, width=400, height= 400, bg="white")
canvas.pack()
rect = canvas.create_rectangle(100, 100, 110, 110, fill='blue')
def move_down(event=None):
    canvas.move(rect, 0, 10)
    root.after(100,move_down)
root.bind('<Enter>', move_down) #or whatever you're binding it to
root.mainloop()
Run Code Online (Sandbox Code Playgroud)

奖励信息:如果你要问"好的,现在当我松开钥匙时如何让矩形停止移动?当我按下其他箭头键时,如何让它在另一个方向上移动?" 这需要更复杂的设计.您需要注册的函数root.after根据矩形的速度移动可变数量的像素,这将根据独立发生的关键事件进行更改.示例实施:

from tkinter import *
root = Tk()
canvas = Canvas(root, width=400, height= 400, bg="white")
canvas.pack()
rect = canvas.create_rectangle(100, 100, 110, 110, fill='blue')
x_velocity = 0
y_velocity = 0

keys_being_held_down = set()
key_accelerations = {
    "Up": (0, -10),
    "Down": (0, 10),
    "Left": (-10, 0),
    "Right": (10, 0)
}

def key_pressed(event):
    global x_velocity, y_velocity

    #ignore autorepeat events
    if event.keysym in keys_being_held_down: 
        return

    keys_being_held_down.add(event.keysym)
    acceleration = key_accelerations[event.keysym]
    x_velocity += acceleration[0]
    y_velocity += acceleration[1]

def key_released(event):
    global x_velocity, y_velocity
    keys_being_held_down.remove(event.keysym)
    acceleration = key_accelerations[event.keysym]
    x_velocity -= acceleration[0]
    y_velocity -= acceleration[1]

def tick():
    canvas.move(rect, x_velocity, y_velocity)
    print(x_velocity, y_velocity)
    root.after(100,tick)

for key in key_accelerations:
    root.bind("<{}>".format(key), key_pressed)
    root.bind("<KeyRelease-{}>".format(key), key_released)

root.after(100, tick)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)

(这不一定是最好的方法,但它演示了基本方法)