1

I would like to learn how to track the mouse movement in a tkinter app that I am designing. I have managed to put together the following code following the example of this question, the output of which is the coordinates of my mouse as it moves through the grid:

import tkinter as tk


class MyGUI(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        # define variables
        GRID = 25
        X = GRID*20
        Y = GRID*15

        wid = 15
        hei = 25

        # create canvas
        self.canvas = tk.Canvas(width=X+1, height=Y+1, background='white',
                                highlightthickness=1, highlightbackground='black')
        self.canvas.pack()

        # create grid
        for i in range(0, Y, GRID):
            self.canvas.create_line(0, i, X, i, fill='gray')
        for i in range(0, X, GRID):
            self.canvas.create_line(i, 0, i, Y, fill='gray')

        # get mouse position
        self.mouse_pos = (0, 0)
        self.bind('<Motion>', self.motion)

    def motion(self, event):
        """Get mouse position"""
        self.mouse_pos = event.x, event.y
        print('{}, {}'.format(event.x, event.y))


if __name__ == "__main__":
    app = tk.Tk()
    app.title('hi')
    MyGUI(app).pack()

    app.mainloop()

However, when I run the code and hover the mouse over the grid, I am not getting anything (no errors and no output). I have played around and managed to change the last few lines 29-39 of the code in the following manner

    # get mouse position
    def motion(event):
        """Get mouse position"""
        x, y = event.x, event.y
        print('{}, {}'.format(event.x, event.y))

    app.bind('<Motion>', motion)

which is included within the class. This seems to work, however I suspect this might be a bad practice or something, if anything it looks significantly different that the example I linked to above and I try to understand why this case works whilst my first attempt doesn't. Thanks for your help in advance.

kostas1335
  • 59
  • 1
  • 6

1 Answers1

0

Here is a code snippet that will display the current mouse position in canvas coordinates.

It uses canvas.canvasx(event.x) and canvas.canvasy(event.y) to generate the correct values.

import tkinter as tk

root = tk.Tk()
frame = tk.LabelFrame(root, labelanchor = tk.S, text = "00|00")
frame.grid(row = 0, column = 0, sticky = tk.NSEW)
canvas = tk.Canvas(frame, width = 640, height = 400)
canvas.grid(row = 0, column = 0, sticky = tk.NSEW)

# get mouse position
def motion(event):
    """Get mouse position"""
    x, y = canvas.canvasx(event.x), canvas.canvasy(event.y)
    frame["text"] = "{}|{}".format(x, y)

canvas.bind("<Motion>", motion)
root.mainloop()
Delrius Euphoria
  • 14,910
  • 3
  • 15
  • 46
Derek
  • 1,916
  • 2
  • 5
  • 15
  • As OP doesn't use scrollbars and hasn't mentioned anything about scrolling why use `canvas.canvasx(event.x)` instead of `event.x`? Also OP's problem is caused by the `self.bind`. – TheLizzard Sep 06 '21 at 12:48
  • My answer addresses the `self.bind` issue. As for `canvasx` vs `event` they both return similar values, with `canvasx, y` returning floats and `event.x, y` returning integers. Using `event.x` and `event.y` will fail if kostas1335 decides to use scrollbars where as canvasx` and `canvasy` will continue to function correctly. They give a superior answer. – Derek Sep 06 '21 at 14:00
  • I really doubt that OP will add scrollbars. Also you didn't actually say that the problem is caused by OP using `self.bind` instead of `self.canvas.bind`. You did change it in your code but OP might miss it. Explicitly saying what the problem is/how to correct it more likely to help OP. – TheLizzard Sep 06 '21 at 14:07
  • Thanks gents, no scrolbars needed hopefully so this should simplify things. – kostas1335 Sep 06 '21 at 14:25