Silken Stream
Silken Stream

Reputation: 11

Keybind within a while loop in pythons turtle

I am attempting to create a study game where a question will fall downward and you type in the answer, however I don't understand how to record key inputs without stopping the motion of the lowering question.

to put simply, I want to be able to lower the question and use my keyboard to input at the same time without stopping the motion.

text_letter = 0

def text_insert(answer):
    global text_letter
    print("hello")
    text_letter += 1

def text_lower(question,answer):
    global text_letter
    text.penup()
    text.goto(random.randint(-250,250),355)
    text.pendown()
    text.color("white")
    text.write("Start", font=("Arial", 20, "normal"))
    x,y = text.pos()
    delay = .01
    wn.textinput("Answer", "Answer:")  
    turtle.listen()
    turtle.onkey(text_insert(answer),answer[text_letter])
    while y > -355:
        time.sleep(delay)
        y -= 1
        text.goto(x,y)
        text.write(question, font=("Arial", 20, "normal"))
        text.clear()

Upvotes: 1

Views: 734

Answers (1)

cdlane
cdlane

Reputation: 41905

This may be a more complicated answer than you anticipated: If you leave off the second, key, argument to the turtle's onkeypress() function, it will call your key press handler code when any key is pressed. It simply won't tell you which key!

We can work around this poor design by rewriting the underlying code to pass tkinter's event.char to the turtle's event handler in the case where no key has been set.

Once that's done, we can use a turtle timed event to lower the question from the top of the window while the user's typed input shows up at the bottom of the window.

Here's my one question simulation of such to help get you started:

from turtle import Screen, Turtle
from functools import partial

FONT_SIZE = 20
FONT = ("Arial", FONT_SIZE, "normal")

def text_lower(question):
    question_turtle.forward(1)
    question_turtle.clear()
    question_turtle.write(question, align="center", font=FONT)
    screen.update()

    if question_turtle.ycor() - answer_turtle.ycor() > FONT_SIZE:
        screen.ontimer(lambda: text_lower(question), 15)
    else:
        question_turtle.clear()

def _onkeypress(self, fun, key=None):
    if fun is None:
        if key is None:
            self.cv.unbind("<KeyPress>", None)
        else:
            self.cv.unbind("<KeyPress-%s>" % key, None)
    else:
        if key is None:
            def eventfun(event):
                fun(event.char)
            self.cv.bind("<KeyPress>", eventfun)
        else:
            def eventfun(event):
                fun()
            self.cv.bind("<KeyPress-%s>" % key, eventfun)

def display_character(character):
    global answer

    if not character:
        return

    if ord(character) == 13:
        answer_turtle.clear()
        answer_turtle.setx(0)
        # do something with answer and then:
        answer = ""
    else:
        answer += character
        answer_turtle.write(character, move=True, font=FONT)

    screen.update()

screen = Screen()
screen.tracer(False)
screen._onkeypress = partial(_onkeypress, screen)

question_turtle = Turtle(visible=False)
question_turtle.penup()
question_turtle.setheading(270)
question_turtle.sety(screen.window_height()/2 - FONT_SIZE)

answer_turtle = Turtle(visible=False)
answer_turtle.penup()
answer_turtle.sety(FONT_SIZE - screen.window_height()/2)

answer = ""

screen.onkeypress(display_character)
screen.listen()

text_lower("What is the air-speed velocity of an unladen swallow?")  # A: An African or European swallow?

screen.mainloop()

Upvotes: 1

Related Questions