'Bind event to click on plot in tkinter canvas

I can bind a click event to a plot (i. e. to print the coordinates that were clicked) like so:

from matplotlib.backend_bases import MouseButton
import matplotlib.pyplot as plt

x = [1, 2, 3, 4]
y = [2, 3, 1, 4]
fig, ax = plt.subplots()
ax.plot(x, y)

def plotClick(event):
   if event.button == MouseButton.LEFT:
      print('Clicked at x=%f, y=%f' %(event.xdata, event.ydata))

plt.connect('button_press_event', plotClick)

plt.show()

I'd like to do the same thing with a plot that is contained within a canvas inside a tkinter window like so:

from matplotlib.backend_bases import MouseButton
import tkinter as tk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

window = tk.Tk()
fig = Figure(figsize=(5, 3))
ax = fig.add_subplot(111)
x = [1, 2, 3, 4]
y = [2, 3, 1, 4]
line, = ax.plot(x, y)
canvas = FigureCanvasTkAgg(fig)
canvas.draw()
canvas.get_tk_widget().pack()

def plotClick(event):
   if event.button == MouseButton.LEFT:
      print('Clicked at x=%f, y=%f' %(event.xdata, event.ydata))

window.mainloop()

What would I have to do to accomplish the same behavior here?

Note: I am aware that one can bind events directly to the canvas using

canvas.get_tk_widget().bind('<Button-1>', plotClick)

with

def plotClick(event):
   print('Clicked at x=%f, y=%f' %(event.x, event.y))

That however uses pixel coordinates on the canvas instead of the coordinates in the plot.



Solution 1:[1]

Instead of using plt.connect, use

canvas.mpl_connect('button_press_event', plotClick)

Using this you can access the coordinates in the plot with event.xdata and event.ydata, but you can also still access the (pixel) coordinates on the canvas using event.x and event.y.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 LukasFun