如何在 python Turtle 图形中检测 X(关闭)按钮?

Posted

技术标签:

【中文标题】如何在 python Turtle 图形中检测 X(关闭)按钮?【英文标题】:How to detect X (close) button in python Turtle graphics? 【发布时间】:2018-11-12 06:24:12 【问题描述】:

当我在 Turtle 图形中运行无限循环绘图时单击 X(关闭)按钮时,会出现一些错误消息。

这是一个例子:

import turtle

wn = turtle.Screen()
tess = turtle.Turtle()

while True:
    tess.forward(50)
    tess.left(120)
    tess.forward(50)

wn.mainloop()

当我关闭窗口时,会显示以下错误消息。

Traceback (most recent call last):
  File "/Users/user/Downloads/test.py", line 8, in <module>
    tess.forward(50)
  File "/Users/user/anaconda3/lib/python3.6/turtle.py", line 1637, in forward
    self._go(distance)
  File "/Users/user/anaconda3/lib/python3.6/turtle.py", line 1605, in _go
    self._goto(ende)
  File "/Users/user/anaconda3/lib/python3.6/turtle.py", line 3178, in _goto
    self._pencolor, self._pensize, top)
  File "/Users/user/anaconda3/lib/python3.6/turtle.py", line 545, in _drawline
    self.cv.coords(lineitem, *cl)
  File "<string>", line 1, in coords
  File "/Users/user/anaconda3/lib/python3.6/tkinter/__init__.py", line 2463, in coords
    self.tk.call((self._w, 'coords') + args))]
_tkinter.TclError: invalid command name ".!canvas"

我想知道如何避免此类错误消息。

有什么方法可以像使用 tkinter 模块中的 Tk 类的“WM_DELETE_WINDOW”选项的“协议”方法一样吗?

【问题讨论】:

您是否知道wn.mainloop() 永远无法运行,因为您的无限循环在那之前? 是的,这就是我的怀疑。下面的答案很好地解释了我想知道的。 【参考方案1】:

是的,这确实可以通过注册一个函数(我称之为on_close,但你可以选择任何函数名)来拦截关闭窗口事件来避免。

一个棘手的事情是protocolTk 类的一个方法。在非乌龟tkinter 用法中,您自己创建Tk 对象作为您的***(或“根”)小部件。由于我们使用的是turtle模块提供的小部件,我们如何访问***小部件?可以通过画布的winfo_toplevel方法获得(可以通过turtle模块或screen对象访问)。

您观察到的错误是由于在窗口(以及画布)已经消失时尝试绘制内容的无限循环造成的。所以下一个棘手的事情是,我们如何防止它尝试这样做?正如Apostolos' answer 对“如何在 Tkinter 中处理窗口关闭事件?”所建议的那样,我们可以使用全局布尔标志。 (就像 Apostolos 一样,我称它为 running。但您可以选择任何对您有意义的名称。)这样,我们的循环就不再那么无限了,它是一个条件循环。因为窗口可能在三个海龟运动之间关闭,所以我也检查了那里的标志:

import turtle

wn = turtle.Screen()
canvas = wn.getcanvas()  # or, equivalently: turtle.getcanvas()
root = canvas.winfo_toplevel()

tess = turtle.Turtle()

def on_close():
    global running
    running = False

root.protocol("WM_DELETE_WINDOW", on_close)

running = True

while running:
    tess.forward(50)
    if not running:
        break
    tess.left(120)
    if not running:
        break
    tess.forward(50)

在我的电脑上,如果没有这两个,它也可以正常工作而不会出现错误消息

    if not running:
        break

零件,但这可能只是幸运的时机,所以我不会依赖它。 (除非有人能解释为什么这总是足够的。)

注意:我不需要在on_close 中调用root.destroy(),因为无论如何循环是程序中运行的最后一件事。 (注意我也不要调用mainloop())所以当我们跳出循环,或者循环因为它的条件不再为真而结束时,程序完成并关闭窗口。

【讨论】:

关于winfo_toplevel 方法的信息很棒。谢谢!

以上是关于如何在 python Turtle 图形中检测 X(关闭)按钮?的主要内容,如果未能解决你的问题,请参考以下文章

Python图形库Turtle

Python中Turtle模块的基本指令有哪些

python之绘制图形库turtle

python:小乌龟turtle

Python turtle库绘制简单图形

python中的turtle库绘制图形