this line of code makes the program unreactive to the restart function

Viewed 51

I try to write a program in python that lets the user to put a bet on one of the turtles and after the race tells him if he was correct or not. I want to let the user choose if he wants to restart the race by clicking 'r' - ( i used the turtle.onkey method) and it worked fine until I put this line of code: bet = screen.textinput("Choose your bet", "Enter blue or green: "). now the program lets the user choose his bet like I wanted but then it wont react when 'r' is pressed.. I want to clarify that after the textinput line of code the program won't react to any of the .onkey methods. anyone has idea why it happens?

THE CODE:

import turtle
import random
import ctypes

speed = random.randint(0, 2)

myTurtle = turtle.Turtle()
myTurtle2 = turtle.Turtle()
screen = turtle.Screen()
def up():
    myTurtle.setheading(90)
    myTurtle.forward(10)

def down():
    myTurtle.setheading(270)
    myTurtle.forward(10)

def left():
    myTurtle.setheading(180)
    myTurtle.forward(10)

def right():
    myTurtle.setheading(0)
    myTurtle.forward(10)

def up2():
    myTurtle2.setheading(90)
    myTurtle2.forward(10)

def down2():
    myTurtle2.setheading(270)
    myTurtle2.forward(10)

def left2():
    myTurtle2.setheading(180)
    myTurtle2.forward(10)

def right2():
    myTurtle2.setheading(0)
    myTurtle2.forward(10)

def restart():
    myTurtle.setposition(400, -300)
    myTurtle.setheading(90)
    myTurtle2.setposition(-400, -300)
    myTurtle2.setheading(90)
    speed = random.randint(0, 2)
    bet = screen.textinput("Choose your bet", "Enter blue or green: ")
    while myTurtle.ycor() < 300 and myTurtle2.ycor() < 300:
        if speed == 1:
            up()
        elif speed == 2:
            up2()
        speed = random.randint(0, 2)
    if myTurtle.ycor() == 300:
        if bet == "blue":
            ctypes.windll.user32.MessageBoxW(0, "Blue is the winner", "You win!", 0x00010000)
        else:
            ctypes.windll.user32.MessageBoxW(0, "Blue is the winner", "You lost", 0x00010000)
    else:
        if bet == "green":
            ctypes.windll.user32.MessageBoxW(0, "Green is the winner", "You win!", 0x00010000)
        else:
            ctypes.windll.user32.MessageBoxW(0, "Green is the winner", "You lost", 0x00010000)

screen.title("Turtle race")
turtle.listen()
myTurtle.shape("turtle")
myTurtle2.shape("turtle")
myTurtle.setposition(400,-300)
myTurtle.setheading(90)
myTurtle2.setposition(-400,-300)
myTurtle2.setheading(90)
myTurtle.dot(10, "blue")
myTurtle2.dot(10, "green")
myTurtle.pencolor("blue")
myTurtle2.pencolor("green")

myTurtle.speed(0)
myTurtle2.speed(0)
bet = screen.textinput("Choose your bet", "Enter blue or green: ")
while myTurtle.ycor() < 300 and myTurtle2.ycor() < 300:
    if speed == 1:
        up()
    elif speed == 2:
        up2()
    speed = random.randint(0, 2)

if myTurtle.ycor() == 300:
    if bet == "blue":
        ctypes.windll.user32.MessageBoxW(0, "Blue is the winner", "You win!", 0x00010000)
    else:
        ctypes.windll.user32.MessageBoxW(0, "Blue is the winner", "You lost", 0x00010000)
else:
    if bet == "green":
        ctypes.windll.user32.MessageBoxW(0, "Green is the winner", "You win!", 0x00010000)
    else:
        ctypes.windll.user32.MessageBoxW(0, "Green is the winner", "You lost", 0x00010000)



turtle.onkey(up, 'Up')
turtle.onkey(down, 'Down')
turtle.onkey(left, 'Left')
turtle.onkey(right, 'Right')

turtle.onkey(restart, 'r')

turtle.onkey(up2, 'w')
turtle.onkey(down2, 's')
turtle.onkey(left2, 'a')
turtle.onkey(right2, 'd')
turtle.mainloop()
1 Answers

Problem is that onkey needs focus on main window to get keys from system but when you execute textinput then this focus is lost and it needs screen.listen() again.


Minimal working code.

Because you repeate some code inside restart() and outside restart() so I run restart() instead of external code.

Because I don't use Windows so I used tkinter.messagebox to display messages. turtle already uses tkinter to display main window with canvas and textinput.

import turtle
import random
#import tkinter  as tk
from tkinter import messagebox

# functions ---

def up():
    myTurtle.setheading(90)
    myTurtle.forward(10)

def down():
    myTurtle.setheading(270)
    myTurtle.forward(10)

def left():
    myTurtle.setheading(180)
    myTurtle.forward(10)

def right():
    myTurtle.setheading(0)
    myTurtle.forward(10)

def up2():
    myTurtle2.setheading(90)
    myTurtle2.forward(10)

def down2():
    myTurtle2.setheading(270)
    myTurtle2.forward(10)

def left2():
    myTurtle2.setheading(180)
    myTurtle2.forward(10)

def right2():
    myTurtle2.setheading(0)
    myTurtle2.forward(10)

def restart():
    myTurtle.setposition(400, -300)
    myTurtle.setheading(90)
    myTurtle2.setposition(-400, -300)
    myTurtle2.setheading(90)
    
    speed = random.randint(0, 2)
    bet = screen.textinput("Choose your bet", "Enter blue or green: ")

    screen.listen()  # <--- set focus on main window after `textinput`
    
    while myTurtle.ycor() < 300 and myTurtle2.ycor() < 300:
        if speed == 1:
            up()
        elif speed == 2:
            up2()
        speed = random.randint(0, 2)

    if myTurtle.ycor() == 300:
        if bet == "blue":
            messagebox.showinfo("Result", "Blue is the winner\n\nYou win!")
        else:
            messagebox.showinfo("Result", "Blue is the winner\n\nYou lost")
    else:
        if bet == "green":
            messagebox.showinfo("Result", "Green is the winner\n\nYou win!")
        else:
            messagebox.showinfo("Result", "Green is the winner\n\nYou lost")
    
# --- main ---

speed = random.randint(0, 2)

myTurtle  = turtle.Turtle()
myTurtle2 = turtle.Turtle()

screen = turtle.Screen()
screen.title("Turtle race")

myTurtle.shape("turtle")
myTurtle2.shape("turtle")

turtle.onkey(up, 'Up')
turtle.onkey(down, 'Down')
turtle.onkey(left, 'Left')
turtle.onkey(right, 'Right')

turtle.onkey(restart, 'r')

turtle.onkey(up2, 'w')
turtle.onkey(down2, 's')
turtle.onkey(left2, 'a')
turtle.onkey(right2, 'd')

restart()

turtle.mainloop()

EDIT:

Reduced code - I keep turtles on list and later I can use myTurtles[number] and I can use one function up(number) instead two functions up() and up2()

import turtle
import random
from tkinter import messagebox

# functions ---

def up(number):
    myTurtles[number].setheading(90)
    myTurtles[number].forward(10)

def down(number):
    myTurtles[number].setheading(270)
    myTurtles[number].forward(10)

def left(number):
    myTurtles[number].setheading(180)
    myTurtles[number].forward(10)

def right(number):
    myTurtles[number].setheading(0)
    myTurtles[number].forward(10)

def restart():
   
    myTurtles[0].setposition(400, -300)
    myTurtles[0].setheading(90)
    myTurtles[1].setposition(-400, -300)
    myTurtles[1].setheading(90)
    
    bet = screen.textinput("Choose your bet", "Enter blue or green: ")
    screen.listen()
    
    speed = random.randint(0, 2)
    while myTurtles[0].ycor() < 300 and myTurtles[0].ycor() < 300:
        if speed < 2: # randint(0, 2) can gives 0, 1, 2  
            up(speed)
        speed = random.randint(0, 2)

    if myTurtles[0].ycor() == 300:
        if bet == "blue":
            messagebox.showinfo("Result", "Blue is the winner\n\nYou win!")
        else:
            messagebox.showinfo("Result", "Blue is the winner\n\nYou lost")
    else:
        if bet == "green":
            messagebox.showinfo("Result", "Green is the winner\n\nYou win!")
        else:
            messagebox.showinfo("Result", "Green is the winner\n\nYou lost")
    
# --- main ---

screen = turtle.Screen()
screen.title("Turtle race")

myTurtles = [
    turtle.Turtle(),
    turtle.Turtle(),
]    

myTurtles[0].shape("turtle")
myTurtles[1].shape("turtle")

turtle.onkey(lambda: up(0),    'Up')
turtle.onkey(lambda: down(0),  'Down')
turtle.onkey(lambda: left(0),  'Left')
turtle.onkey(lambda: right(0), 'Right')

turtle.onkey(lambda: up(1),    'w')
turtle.onkey(lambda: down(1),  's')
turtle.onkey(lambda: left(1),  'a')
turtle.onkey(lambda: right(1), 'd')

turtle.onkey(restart, 'r')

restart()

turtle.mainloop()
Related