【问题标题】:Python tkinter Canvas root.after() maximum recursion depth exceededPython tkinter Canvas root.after() 超出最大递归深度
【发布时间】:2016-05-21 01:26:56
【问题描述】:
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('<Down>', move_down)
root.mainloop()

我似乎不知道如何使root.after() 工作。我该如何解决这个问题,让矩形继续向下移动?

【问题讨论】:

    标签: python canvas tkinter tkinter-canvas


    【解决方案1】:

    短版:您不能在传递给after 的函数上加上括号。

        root.after(1,move_down(event))
    

    此行没有将函数move_down 注册为after 事件的回调。相反,它会立即调用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()
    

    奖励信息:如果您要问“好的,现在我如何让矩形在我释放键时停止移动?当我按下其他箭头键时如何让它向另一个方向移动?”这需要更复杂的设计。您需要注册到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()
    

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

    【讨论】:

      【解决方案2】:

      我建议不要使用root.after(),这样当你点击时它会移动,当你停止点击时它不会移动

      【讨论】:

      猜你喜欢
      • 2017-07-18
      • 2011-12-31
      • 1970-01-01
      • 2020-07-13
      • 2021-02-07
      • 2017-03-18
      • 2015-04-15
      • 1970-01-01
      • 2013-12-01
      相关资源
      最近更新 更多