首页 > 解决方案 > 在嵌入 tkinter 的 matplotlib 图中获取鼠标点击的坐标

问题描述

我在带有 FigureCanvasTkAgg 的 tkinter 接口中嵌入了一个 matplotlib 图,整个事情都在一个类中。

我想获得鼠标点击的数据坐标(目的是在鼠标点击上放置一个点),到目前为止没有任何效果。我尝试了两种选择:直接在画布的小部件上使用 .bind,以及使用 figure.canvas.mpl_connect。

如果我选择第一个选项,在画布的小部件上使用 .bind,我可以访问 event.x 和 event.y,但不能访问 event.xdata 和 event.ydata - 这是可以理解的。然后我需要用 ax.transData.inverted().transform(()) 转换 event.x 和 event.y - 这里的问题是 Y 坐标是倒置的,因为在小部件中,y 坐标向下增加,而在图中 y坐标向上增加。例如。0.6 应该是 0.4。此外,当我在轴外单击时,行为很时髦。

如果我选择第二个选项,使用 figure.canvas.mpl_connect,它应该让我与 event.xdata 和 event.ydata 直接数据坐标,没有任何反应。

代码如下:

进口

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

创建一个图形并返回它的函数:

def figure_create():
 fig=Figure(figsize=(10,10))
 ax=fig.add_subplot(111)
 return(fig)

我的课

class GToplevel()   
    
 def __init__(self,data=None):
    self.master=tk.Toplevel()
    figure=figure_create()  #creates a figure
    canvas=FigureCanvasTkAgg(figure,master=self.master) #creates a canvas
    self.figure=figure
    self.canvas=canvas
    widget=canvas.get_tk_widget()
    widget.pack()
    canvas.draw() #draws canvas
    
    #FIRST OPTION
    #widget.bind("<Button-1>",self.click_coordinate) #binds the click to a function
    #Y coordinate is inverted
    
    #SECOND OPTION
    #figure.canvas.mpl_connect('button_press_event', self.click_coordinate)
    #nothing seems to happen

 def click_coordinate(self,event):
    
    x=event.x #x coordinate of event, not Data
    y=event.y #y coordinate of event, not Data
    print(x,y)  #checking that the coordinates are right
    canvas=self.canvas
    figure=self.figure
    ax=figure.get_axes()[0] #the only subplot of a figure
  
    inv = ax.transData.inverted() 
    x,y=inv.transform((x,y))      #turns x,y into Data coordinates
    
    canvas.draw()

标签: python-3.xmatplotlibtkintertkinter-canvas

解决方案


答案在课外。重写代码:

class GToplevel(): 

def __init__(self,data=None):
    self.master=tk.Toplevel()
    figure=figure_create()  #creates a figure
    canvas=FigureCanvasTkAgg(figure,master=self.master) #creates a canvas
    self.figure=figure
    self.canvas=canvas
    widget=canvas.get_tk_widget()
    widget.pack()
    canvas.draw() #draws canvas

    figure.canvas.callbacks.connect('button_press_event', self.callback)

def callback(self,event):
    x=event.xdata
    y=event.ydata
    print(x,y)

我可以使用 event.xdata 和 event.ydata 直接访问数据坐标,但必须调用 figure.canvas.callbacks.connect。这不起作用,因为我的主要代码是:

root=tk.Tk()
GToplevel()
root.mainloop()

但是当我这样修改第二行时:

g=GToplevel()

一切正常。

我不知道为什么会这样,但这解决了我的问题。


推荐阅读