繁体   English   中英

海龟图形:如何实现暂停功能?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM