Search code examples
pythonpython-3.xturtle-graphicspython-turtle

Python multiple turtle.ondrag not working


I have been writing program about dragging turtles to different designated position.

However, turtle.ondrag(turtle.goto) nor at[i].ondrag(at[i].goto) does not work.

I've been amended with the solution from here Python turtle.ondrag not working @ Jellominer, but that's seems not working for my case (with multiple turtles). The code snippet at below.

import turtle as t

def handler(x, y, i):
    global at
    curTurtle = at[i]
    curTurtle.ondrag(None)  # disable handler inside handler
    curTurtle.setheading(curTurtle.towards(x, y))  # turn toward cursor
    curTurtle.goto(x, y)  # move toward cursor
    print(x, y, i)
    curTurtle.ondrag(handler)


at = []
for i in range(3):
    at.append(t.Turtle())

# Just to seperated turtles with color
at[0].color('grey')
at[0].goto(100, 100)
at[1].color('blue')
at[1].goto(0, 100)
at[2].color('green')
at[2].goto(100, 0)

for i in range(3):
    at[i].ondrag(lambda x, y: handler(x, y, i))



t.listen()
t.mainloop()

Only the turtle with the largest index could be dragged, as seen from the print(x, y, i). It's there anyways to let the drag other turtle move as well?


Solution

  • This where classes come in handy. The easiest way to solve this is to subclass the Turtle object and create the handler as an instance method, then when you construct the turtle you can assign it's ondrag listener to it's own version of the handler.

    You might also want to bump the screen tracer a tiny bit so you don't get the lagging effect.

    import turtle as t
    
    class T(t.Turtle):
        def dragging(self, x, y):
            self.ondrag(None)
            self.setheading(self.towards(x,y))
            self.goto(x,y)
            self.ondrag(self.dragging)
    
    at = []
    for i in range(3):
        turtle = T()
        turtle.ondrag(turtle.dragging)
        at.append(turtle)
    
    
    # Just to seperated turtles with color
    at[0].color('grey')
    at[0].goto(100, 100)
    at[1].color('blue')
    at[1].goto(0, 100)
    at[2].color('green')
    at[2].goto(100, 0)
    
    # t.Screen().tracer(3)   # uncomment to remove lagging.
    t.listen()
    t.mainloop()