Search code examples
pythontkinterpython-turtle

how do i keep turtle.Screen() running AND take commands to move/ turn turtle?


I am trying to basically make a copy version of LOGO but in my style (be easy on me). So similar to LOGO (but not quite similar) i want to keep taking inputs in powershell and see the changes in the screen simultaneously. BUT in this code the screen just opens and thats it, no prompt for input. Help me. Here is the code:

#----------------
# turtle paint
#----------------

import turtle


def main():
    
    bg_color = input("What backgroud color would you like?")    # taking input for bg_color
    tur_color = input("What color of turtle will you like?")

    wn = turtle.Screen()        # creates a screen for turtle drawing
    wn.bgcolor(bg_color)
    tur = turtle.Turtle()           # tur is assigned Turtle
    
    move()

    print("Thank you for using Turtle paint.")

def move():
    wn.mainloop()
    print("Turtle is facing 'RIGHT'.")
    while True:
        
        try:                # to eliminate unnecessarily errors from popping up
            q = input("Turn or move forward?\nturn/forward> ")      # turn or move forward prompt
            
            # based on the answer take input of degree and forward movement length
            if q.lower() == "turn":
                turn = input("Turn 'Right' or 'Left'?")
                degree = int(input(f"Turn {turn} by how much degree"))
                if turn.lower() == 'right':
                    tur.right(degree)
                elif turn.lower() =='left':
                    tur.left(degree)
            
            elif q.lower() == 'forward':
                movement = int(input("How much forward? type in number\n> "))
                tur.forward(movement)
        
        except:
            print('Turtle didnt catch that, try again!')
        
        # if the user want to continue or not
        # there is semantic error probably
        print("Wanna continue?")
            ans = input('> ')       
            if ans in ['yes', 'Yes', "YES", 'Y' ,'y']:
                pass
            else:
                break

if __name__ == '__main__':
    main()

Solution

  • Try something like this:

    #----------------
    # turtle paint
    #----------------
    
    import turtle
    from threading import Thread
    
    
    def main():
        global wn, tur
    
        wn = turtle.Screen()
        tur = turtle.Turtle()
    
        move()
    
    def move_asker():
        print("Turtle is facing \"RIGHT\".")
        while True:
            try:
                q = input("Turn or move forward?\nturn/forward/exit> ")
    
                if q.lower() == "turn":
                    turn = input("Turn right or left? ")
                    degree = int(input(f"Turn {turn} by how much degree"))
                    if turn.lower() == "right":
                        tur.right(degree)
                    elif turn.lower() == "left":
                        tur.left(degree)
    
                elif q.lower() == "forward":
                    movement = int(input("How much forward? type in number\n> "))
                    tur.forward(movement)
    
                elif q.lower() == "exit":
                    wn.destroy()
                    break
    
            except RuntimeError:
                # The user might have closed the window
                break
    
            except Exception as error:
                print("Error = " + repr(error))
                print("Turtle didnt catch that, try again!")
    
    def move():
        thread = Thread(target=move_asker, daemon=True)
        thread.start()
        wn.mainloop()
    
    if __name__ == "__main__":
        main()
    

    In the move function, it tells python to start executing move_asker() and continue executing wn.mainloop().

    However there are problems with this approach. One of them is that turtle might crash without even giving you an error. That is why it isn't advisable to use turtle with threads. I tested all of the commands that are in the program right now and they should work.

    It would be better if you switch from using turtle and use something like tkinter (turtle was built on top of tkinter so it shouldn't be that hard). If you do that, you use an Entry instead of using input(...). It will solve the problem outlined above.