【问题标题】:RecursionError on macOS with tkinter moving objects带有 tkinter 移动对象的 macOS 上的 RecursionError
【发布时间】:2020-02-14 20:20:21
【问题描述】:

我正在使用 tkinter 学习,这涉及到形状的流畅运动。这就是我现在卡住的地方。

我得到不一致的递归错误。该代码在 Windows 1O 上运行没有问题,但在我的 macOS 上它崩溃了。

此外,如果递归之间的时间≥ 17 毫秒,它就会停止出错并按预期运行。我已经简化了代码,只是为了解决一个问题。

from tkinter import *
master = Tk()
canvas = Canvas(bg = "gray", width = 1000, height = 800)
canvas.pack()
cara = canvas.create_line(100,100,900,100, width = 5, fill = "red")

def moveCara():
    canvas.move(cara, 0,1)
    canvas.after(16, moveCara)  # Here is the time setting, change it to 17 and the thing
                                # does not crash.
    canvas.update()

moveCara()
mainloop()

此代码导致我的 MacBook 崩溃:

RecursionError: maximum recursion depth exceeded during compilation

但是,如果我将 canvas.after() 中的时间更改为 17 或更大,一切正常。这是为什么呢?

【问题讨论】:

  • 尽量不要打电话给canvas.update()
  • 另外,取决于你想做什么。 pygame 将是一个很好的库。
  • 尝试调用canvas.update_idletasks() 而不是canvas.update()。后者“可能导致不可预测的行为或循环”。见Universal widget methods

标签: python macos tkinter


【解决方案1】:

问题出在这行代码:

canvas.update()

您绝对不应该在从事件处理程序调用的函数中调用update(并且通过after 运行函数被视为事件处理程序)。完全没有必要让您的程序正常工作,需要将其删除。

发生的情况是,您对after 的调用增加了mainloop 在给定时间后需要完成的一些工作。当您调用update 时,如果给定的时间已经过去,它会执行该工作,否则它可能根本不做任何事情。

如果您的计算机速度足够慢,那么当您调用update 时,您的动画的下一帧就已经到了。这会导致moveCora 在第一次调用返回之前通过canvas.update() 再次调用。这就是你得到递归错误的原因。

我无法在 16 毫秒时在我的机器上复制问题,但是当我将时间移到 5 毫秒时,我能够重现它。你必须有一台机器需要超过 16ms 才能移动线路,然后调用after。当我删除对 canvas.update() 的调用时,我可以将值设置为 1ms 而不会出现问题。

【讨论】:

    猜你喜欢
    • 2023-03-22
    • 2020-03-19
    • 1970-01-01
    • 2017-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多