Как обнаружить кнопку X (закрыть) в графике Python Turtle? - PullRequest
0 голосов
/ 02 июня 2018

Когда я нажимаю кнопку X (закрыть) во время выполнения бесконечного цикла рисования в графике Turtle, появляются некоторые сообщения об ошибках.

Вот пример:

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"

Мне интересно, как можно избежать таких сообщений об ошибках.

Есть ли способ, подобный использованию метода «protocol» сОпция "WM_DELETE_WINDOW" класса Tk из модуля tkinter?

1 Ответ

0 голосов
/ 02 июня 2018

Да, этого действительно можно избежать, зарегистрировав функцию (я назвал ее on_close, но вы можете выбрать любое имя функции) для перехвата события закрытия окна.

Одна хитрость в том, что protocol это метод класса Tk.При использовании не-черепахи tkinter вы сами создаете объект Tk в качестве виджета верхнего уровня (или «корня»).Поскольку мы используем виджеты, предоставляемые модулем turtle, как мы можем получить доступ к виджету верхнего уровня? Он доступен через winfo_toplevel метод canvas (который можетбыть доступным через модуль turtle или экранный объект).

Наблюдаемая вами ошибка вызвана бесконечным циклом, пытающимся рисовать вещи, когда окно (а вместе с ним и холст) уже ушло,Итак, следующая хитрость в том, как мы можем предотвратить попытки этого сделать?В соответствии с рекомендацией Apostolos ' «Как мне обработать событие закрытия окна в Tkinter?», Мы можем использовать глобальный логический флаг.(Точно так же как Апостолос, я назвал это 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

части, но это может быть просто удачное время, поэтому я бы не стал на это полагаться.(Если кто-то не может объяснить, почему этого всегда должно быть достаточно.)

Примечание: Мне не нужно было вызывать root.destroy() в on_close, потому что цикл - это последнее, что нужно запуститьво всяком случае в программе.( обратите внимание , что я также не вызываю mainloop()) Поэтому, когда мы вырываемся из цикла или цикл завершается, потому что его условие больше не выполняется, программа завершается изакрывает окно.

...