[英]turtle graphics: How do I implement a pause function?
我正在尝试使用 python 3 海龟图形来做一些类似演示软件的事情:画一些东西,暂停按键以便演示者可以解释,然后绘制下一个东西。
这是我尝试过的一种解决方案(不起作用):
import turtle
import time
paused = False
def unpause():
print("unpause() called")
global paused
paused = False
def pause():
global paused
paused = True
while paused:
time.sleep(0.1)
t = turtle.Turtle()
# set up listener
t.screen.listen()
t.screen.onkeypress(unpause)
# draw something
t.hideturtle()
t.pensize(5)
t.speed(1)
t.pu()
t.goto(-300,-300)
t.pd()
t.goto(-300, 300)
# pause until key is pressed
pause()
# draw some more
t.pu()
t.goto(300,-300)
t.pd()
t.goto(300, 300)
t.screen.mainloop()
问题是睡眠调用循环完全阻止了按键被检测到,即使我使用非常短(100 毫秒)睡眠的 while 循环也是如此。
如果我在绘制第一行时按下一个键,我会在控制台中看到“unpause() 调用”,所以我知道键绑定处于活动状态。
为什么没有检测到按键? 我不知道内部原理,但我认为击键会记录在某个缓冲区中,并且在睡眠调用之间的休息期间,侦听器将读取缓冲区并取消设置paused
全局变量。 这不会发生。
有没有其他方法可以实现这个?
这是在 Debian Linux 系统上。
海龟图形基于tkinter
,它是一个事件驱动的 GUI 框架,所以你不能像在常规的程序驱动程序中那样做 - 请参阅@Bryan Oakley 对Tkinter问题的回答- 随着时间的推移执行函数更详细的解释(尽管turtle
模块隐藏了大部分细节)。 无论如何,这个事实意味着你不应该像这样在一个紧凑的循环中调用time.sleep()
,因为一切都必须在不干扰mainloop()
运行的情况下发生。
该“绝招”,以避免调用time.sleep()
是使用调度全局变量的定期检查turtle.ontimer()
函数-如果它的第一部分被改变,你的程序将工作如下图所示:
import turtle
paused = False
def unpause():
print("unpause() called")
global paused
paused = False
def pause():
global paused
paused = True
pausing() # Start watching for global to be changed.
def pausing():
if paused:
turtle.ontimer(pausing, 250) # Check again after delay.
# else quit checking.
t = turtle.Turtle()
# set up listener
t.screen.onkeypress(unpause) # Reversed order of
t.screen.listen() # these two statements.
# draw something
t.hideturtle()
t.pensize(5)
t.speed(1)
t.pu()
t.goto(-300,-300)
t.pd()
t.goto(-300, 300)
# pause until key is pressed
pause()
# draw some more
t.pu()
t.goto(300,-300)
t.pd()
t.goto(300, 300)
t.screen.mainloop()
采纳您的建议给我的想法(感谢 martineau 和 kederrac!)我想出了一个解决方案。 它涉及将我的每个绘图任务包装在一个函数中,然后使用一个调度函数,该函数要么等待带有ontimer
循环的按键,要么调用下一个绘图函数。
这个概念验证代码使用了太多的全局变量,但它展示了技术:
import turtle
t = turtle.Turtle()
paused = False
current_task = 0
def unpause():
global paused
paused = False
def turtle_setup():
global t
t.screen.onkeypress(unpause)
t.screen.listen()
t.hideturtle()
t.pensize(5)
t.speed(1)
def draw_task_finished():
global paused, current_task, drawing_tasks
current_task += 1
paused = True
if current_task < len(drawing_tasks):
draw_task_after_keypress()
def draw_task_after_keypress():
global paused, current_task
if paused:
turtle.ontimer(draw_task_after_keypress, 100)
else:
drawing_tasks[current_task]()
def draw_thing_one():
global t
t.pu()
t.goto(-300,-300)
t.pd()
t.goto(-300, 300)
draw_task_finished()
def draw_thing_two():
global t
t.pu()
t.goto(300,-300)
t.pd()
t.goto(300, 300)
draw_task_finished()
drawing_tasks = [draw_thing_one, draw_thing_two]
turtle_setup()
drawing_tasks[0]()
t.screen.mainloop()
您可以使用turtle.done() function.
只需创建一个 input() 函数,如果输入,程序就会运行。 我用基本方法尝试了这个。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.