0

This code should utilize mouse motion events to draw a dot at the current mouse position:

import turtle

def motion(event):
    x, y = event.x, event.y
    turtle.goto(x-300, 300-y)
    turtle.dot(5, "red")

turtle.pu()
turtle.setup(600, 600)
turtle.hideturtle()
canvas = turtle.getcanvas()
canvas.bind("<Motion>", motion)

The code works as expected for a few seconds or longer if the mouse is moved very slowly. Then it throws:

>>> 
====================== RESTART: C:/code/turtle_move.py 
======================
>>> Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\...\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1698, in __call__
    args = self.subst(*args)
  File "C:\Users\...\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1428, in _substitute
    e.type = EventType(T)
RecursionError: maximum recursion depth exceeded

=============================== RESTART: Shell 
===============================
>>>

Any help is much appreciated.

cdlane
  • 40,441
  • 5
  • 32
  • 81
user2757572
  • 463
  • 1
  • 4
  • 9
  • What have you done to trace the execution? At least insert one or two strategy `print` statements to show what is getting called. – Prune Oct 30 '18 at 00:09

1 Answers1

2

The problem is that a new event comes in while your event hander is still processing the previous event, so the event handler gets called from inside the event handler which looks like a recursion! The fix is to disable the event binding while inside the event handler:

from turtle import Screen, Turtle

def motion(event):
    canvas.unbind("<Motion>")
    turtle.goto(event.x - 300, 300 - event.y)
    turtle.dot(5, "red")
    canvas.bind("<Motion>", motion)

screen = Screen()
screen.setup(600, 600)

turtle = Turtle(visible=False)
turtle.speed('fastest')
turtle.penup()

canvas = screen.getcanvas()
canvas.bind("<Motion>", motion)
screen.mainloop()
cdlane
  • 40,441
  • 5
  • 32
  • 81
  • That was also my assumption but then I was wondering why a turtle.goto would trigger a mousemove event. Thank you very much. – user2757572 Oct 30 '18 at 15:36