Графика черепахи: Как мне реализовать функцию паузы? - PullRequest
0 голосов
/ 29 марта 2020

Я пытаюсь использовать 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()

Проблема в том, что спящий вызов l oop полностью блокирует обнаружение нажатия клавиши, даже когда я использую некоторое время l oop очень коротких (100 мс) снов.

Если я нажимаю клавишу во время рисования первой строки, я вижу "unpause () call" в моей консоли, поэтому я знаю, что привязка клавиш активна.

Почему не обнаруживается нажатие клавиши? Я не знаю насчет внутренних функций, но я думал, что нажатие клавиши будет записано где-нибудь в буфере, и во время перерыва между вызовами в режиме ожидания слушатель будет читать буфер и сбрасывать глобальную переменную paused. Этого не происходит.

Есть ли другой способ реализовать это?

Это в системе Debian Linux.

Ответы [ 2 ]

0 голосов
/ 30 марта 2020

Принимая идеи, которые ваши предложения дали мне (спасибо Мартино и Кедерра c!), Я смог найти решение. Это включает в себя завершение каждой из моих задач рисования в функции, а затем использование функции диспетчеризации, которая либо ждет нажатия клавиши с ontimer l oop, либо вызывает следующую функцию рисования.

Это подтверждение -концептный код использует слишком много глобалов, но показывает технику:

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()
0 голосов
/ 29 марта 2020

Графика черепахи основана на tkinter, который является управляемым событиями фреймворком GUI, поэтому вы не можете делать то, что делаете в обычной процедурно-управляемой программе - см. Ответ @Bryan Oakley на вопрос Tkinter - выполнение функций со временем для более подробного объяснения (хотя модуль turtle скрывает большинство этих деталей). Во всяком случае, этот факт означает, что вы не должны вызывать time.sleep() в узком l oop, как это, потому что все должно происходить без вмешательства в выполнение mainloop().

«Трюк», чтобы избежать вызова time.sleep() предназначен для планирования периодов c проверок глобальной переменной с использованием функции 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...