在完成路径之前,单击下面程序中的reset
按钮,我会遇到一些奇怪的行为。当我这样做时,乌龟会加速并不稳定地移动,同时基本上仍会紧贴小路。我按reset
的次数越多,机芯变得越发呆。
有人可以解释一下如何使reset
按钮完全重置路径并避免上述问题吗?
import turtle
import tkinter as tk
def create_reset_button_tkinter():
"""An alternative approach to creating a button using Tkinter."""
canvas = screen.getcanvas()
button = tk.Button(canvas.master, text="Reset", background="green", foreground="white", bd=0,
activebackground="green", activeforeground="white", command=reset)
canvas.create_window(-100, 100, window=button)
def reset():
global path_iter
bob.goto(0, 0)
path = [(0, 0), (20, 0), (20, 20), (20, 30), (30, 20), (40, 20), (40, 30), (50, 30), (60, 30), (60, 40)]
path_iter = iter(path)
go_to_next_coord()
def go_to_next_coord():
try:
next_coord = next(path_iter)
except StopIteration:
return
bob.goto(next_coord)
turtle.ontimer(go_to_next_coord, 500)
screen = turtle.Screen()
create_reset_button_tkinter()
bob = turtle.Turtle("square")
bob.penup()
path = [(0, 0), (20, 0), (20, 20), (20, 30), (30, 20), (40, 20), (40, 30), (50, 30), (60, 30), (60, 40)]
path_iter = iter(path)
go_to_next_coord()
turtle.done()
[您可以在Reset()
函数中检查当前迭代器中是否还有项目,如果没有,请调用go_to_next_coord()
重新启动海龟计时器:
def reset():
global path_iter
num_of_items = len(list(path_iter)) # get the number of items in current iterator
#bob.goto(0, 0) # no need to call here as it will be executed in next call of go_to_next_coord()
path = [(0, 0), (20, 0), (20, 20), (20, 30), (30, 20), (40, 20), (40, 30), (50, 30), (60, 30), (60, 40)]
path_iter = iter(path)
if num_of_items == 0:
# restart turtle timer
go_to_next_coord()
我尚不清楚使用iter
有什么好处,特别是当@ acw1668对代码的修复必须将iter
转换回list
时:
num_of_items = len(list(path_iter))
为什么不首先使用list
:
from turtle import Screen, Turtle
from tkinter import Button
PATH = [ \
(0, 0), (20, 0), (20, 20), (20, 30), (30, 20), \
(40, 20), (40, 30), (50, 30), (60, 30), (60, 40), \
]
semaphore = 0
def reset():
global semaphore
if semaphore:
return # reset already executing when 'Reset' pressed
semaphore += 1
empty = len(path_list) == 0
path_list[:] = PATH # reload path coordinates
turtle.home()
if empty:
screen.ontimer(go_to_next_coord) # execute shortly after this function exits
semaphore -= 1
def go_to_next_coord():
if not semaphore:
try:
turtle.goto(path_list.pop(0))
except IndexError:
return
screen.ontimer(go_to_next_coord, 500)
def create_reset_button_tkinter():
""" An alternative approach to creating a button using Tkinter. """
canvas = screen.getcanvas()
button = Button(canvas.master, text="Reset", command=reset)
canvas.create_window(-100, 100, window=button)
screen = Screen()
create_reset_button_tkinter()
turtle = Turtle("square")
turtle.penup()
path_list = list(PATH)
go_to_next_coord()
screen.mainloop()
我发现在两个实现中仍然可能导致行为不正确的两个问题:首先,go_to_next_coord()
可以在reset()
方法期间执行。 (例如,当您要求乌龟做某事时,这会短暂地将控制权移交给事件处理程序,并允许计时器触发。)这会引起罕见的意外视觉故障。
[其次,如果按钮是由乌龟onclick()
触发的,我通常会取消设置事件处理程序代码内的事件处理程序映射(直到返回之前),以防止事件[[stacking。但是,由于这是一个tkinter按钮,因此这超出了Turtle的控制范围。 (一遍又一遍地按“重置”。)
semaphore
变量。 (尽管您也可以通过tkinter命令禁用和重新启用按钮事件。)不够完美,但是更好。