Soda
Soda

Reputation: 89

Tkinter: Get mouse coordinates only when mouse button is pressed

I have a rather specific question in Python.

I know the solution for constantly recieving the mouse coordinates on a frame in Tkinter:

import Tkinter as tk
root = tk.Tk()

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

root.bind('<Motion>', motion)
root.mainloop()

My question is now combining a button pressed and the motion event. In a nutshell: I want the mouse coordinates only when the button is pressed, not when it's released or not pressed.

def ButtonPress(event):
    #This is the part, where I can't figure out, how to proceed.
    #How can I call the motion event from here.


Bt = Button(root, text='Press for coordinates!')
Bt.bind('<ButtonPress>', ButtonPress)

Regards!

Upvotes: 1

Views: 2220

Answers (2)

Bryan Oakley
Bryan Oakley

Reputation: 386352

There are at least two very simple solutions:

  • set/unset a flag on button press/release, and in your function only print the coordinates if the flag is set,
  • bind/unbind the motion event on button press/release.

Setting a flag

This example uses a flag named do_capture which is set to True with a button press and set to False on a button release:

import Tkinter as tk
root = tk.Tk()

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

def capture(flag):
    global do_capture
    do_capture = flag

root.bind('<Motion>', motion)
root.bind("<ButtonPress-1>", lambda event: capture(True))
root.bind("<ButtonRelease-1>", lambda event: capture(False))

capture(False)

root.mainloop()

Bind/Unbind

In this example, we bind the <Motion> event on the press of a button and unbind it on the release:

import Tkinter as tk
root = tk.Tk()

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

def capture(flag):
    if flag:
        root.bind('<Motion>', motion)
    else:
        root.unbind('<Motion>')

root.bind("<ButtonPress-1>", lambda event: capture(True))
root.bind("<ButtonRelease-1>", lambda event: capture(False))

root.mainloop()

Upvotes: 1

docair
docair

Reputation: 76

If you don't want to store the mouse position in the motion callback and then read it again in the button's callback, you can use winfo_pointer() to get the absolute pointer position on your screen and subtract the window position winfo_root() to get the pointer position relative to the window.

Of course, you would need to catch pointer positions outside the window yourself.

Upvotes: 0

Related Questions