helpneeded92
helpneeded92

Reputation: 41

turtle - How to get mouse cursor position in window?

How would I go about finding the current position of the mouse pointer in the turtle screen? I want it so I have the mouse position before I click and while im moving the cursor. I have searched google and this website can't find anything besides how to get the position after a click.

Upvotes: 4

Views: 19298

Answers (2)

ggorlen
ggorlen

Reputation: 56885

Following up on this answer, here's an example of one way to normalize the Tkinter coordinates for turtle using the canvas.bind('<Motion>', motion) approach (canvas.winfo_pointerxy() didn't provide values that made sense to me, although I didn't look into it much):

import turtle


def on_motion(event):
    x = event.x - turtle.window_width() / 2
    y = -event.y + turtle.window_height() / 2
    turtle.goto(x, y)
    turtle.stamp()
    print(x, y)


turtle.tracer(0)
turtle.penup()
turtle.getcanvas().bind("<Motion>", on_motion)
turtle.exitonclick()

Using this in a real-time app rather than only on motion:

import turtle


def on_motion(event):
    global mouse_x, mouse_y
    mouse_x = event.x - turtle.window_width() / 2
    mouse_y = -event.y + turtle.window_height() / 2


def tick():
    print(mouse_x, mouse_y)
    turtle.goto(mouse_x, mouse_y)
    turtle.stamp()
    win.ontimer(tick, frame_delay_ms)


turtle.tracer(0)
mouse_x, mouse_y = 0, 0
turtle.getcanvas().bind("<Motion>", on_motion)
turtle.shape("circle")
turtle.penup()
frame_delay_ms = 1000 // 30
win = turtle.Screen()
tick()
turtle.exitonclick()

Putting it into a more full-featured app without global:

import turtle
from math import sin


def add_mouse_listener():
    def on_motion(event):
        nonlocal x, y
        x = event.x - turtle.window_width() / 2
        y = -event.y + turtle.window_height() / 2

    turtle.getcanvas().bind("<Motion>", on_motion)
    x, y = 0, 0
    return lambda: (x, y)


def color(c, a):
    return sin(c + a) / 2 + 0.5


def colors(r, ra, g, ga, b, ba):
    return color(r, ra), color(g, ga), color(b, ba)


def main():
    ra = 0
    ba = 0
    ga = 0
    r = 0.5
    b = 0
    g = 1
    frame_delay_ms = 1000 // 30
    turtle.tracer(0)
    turtle.pensize(40)
    mouse_pos = add_mouse_listener()
    win = turtle.Screen()

    def tick():
        nonlocal ra, ba, ga
        turtle.color(colors(r, ra, g, ga, b, ba))
        ra += 0.03
        ba += 0.0311
        ga += 0.032
        x, y = mouse_pos()
        turtle.setheading(turtle.towards(x, y))
        turtle.forward(10)
        turtle.update()
        win.ontimer(tick, frame_delay_ms)

    tick()
    turtle.exitonclick()


if __name__ == "__main__":
    main()

Upvotes: 2

das-g
das-g

Reputation: 9994

turtle.getcanvas() returns a Tkinter Canvas.

Like with a Tkinter window, you can get the current mouse pointer coordinates by winfo_pointerx and .winfo_pointery on it:

canvas = turtle.getcanvas()
x, y = canvas.winfo_pointerx(), canvas.winfo_pointery()
# or
# x, y = canvas.winfo_pointerxy()

If you want to only react to movement instead of e.g. polling mouse pointer positions in a loop, register an event:

def motion(event):
    x, y = event.x, event.y
    print('{}, {}'.format(x, y))

canvas = turtle.getcanvas()
canvas.bind('<Motion>', motion)

Note that events only fire while the mouse pointer hovers over the turtle canvas.

All these coordinates will be window coordinates (with the origin (0, 0) at the top left of the turtle window), not turtle coordinates (with the origin (0, 0) at the canvas center), so if you want to use them for turtle positioning or orientation, you'll have to do some transformation.

Upvotes: 10

Related Questions