使用 Tkinter 获取 Matplotlib 中鼠标单击的位置



我正在尝试用python编写一个简单的GUI,它显示一个绘图,然后允许用户单击某些关键特征(转折点等(,然后将其用作我正在开发的拟合算法的起点。

我找到了以下线程来启动我;使用 matplotlib 存储鼠标单击事件坐标

从计算机的角度来看,这似乎只给了我鼠标的像素位置。理想情况下,我想要的是能够获取工具栏右侧的坐标并使用这些坐标;尝试编写自己的像素>数据转换似乎是一种耻辱,而 Matplotlib 显然已经在某个地方为我做了这件事。

这是我到目前为止的代码,如果看起来我以错误的方式处理问题,请告诉我,我不太自豪地重新开始。

import matplotlib
matplotlib.use('TkAgg')
import Tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.backend_bases import MouseEvent
from matplotlib.figure import Figure
import numpy as np

def callback(event):
    print "clicked at", event.x, event.y
root = tk.Tk()
f = Figure(figsize=(5,4), dpi=100)
a = f.add_subplot(111)
t = np.arange(0.0,3.0,0.01)
s = np.sin(2*np.pi*t)
a.plot(t,s)
canvas = FigureCanvasTkAgg(f, master=root)
canvas.show()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
canvas.mpl_connect('button_press_event',callback)
def callback(event):
    print "clicked at", event.xdata, event.ydata
toolbar = NavigationToolbar2TkAgg( canvas, root )
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
toolbar
root.mainloop()

编辑:我没有完全阅读您的示例就跳入回答。 您遇到的问题是由于您定义事物的顺序造成的。基本上,你有:

import matplotlib.pyplot as plt
def callback(event):
    print event.x, event.y
fig, ax = plt.subplots()
fig.canvas.callbacks.connect('button_press_event', callback)
def callback(event):
    print event.xdata, event.ydata

连接回调时,尚未定义第二个函数,因此它将连接到具有相同名称的较早函数。 要么在定义函数后移动回调连接,要么只是向上移动函数定义并删除(未使用的(第一个回调函数。

无论如何,请查看 matplotlib 的转换,以了解如何在显示/像素坐标和绘图坐标之间进行转换。 我会留下我原来的答案,希望它能帮助遇到这个问题的其他人。


如果我理解正确,您想要鼠标单击发生的数据坐标吗?

如果是这样,请使用 event.xdataevent.ydata

举个简单的例子:

import matplotlib.pyplot as plt
def on_click(event):
    if event.inaxes is not None:
        print event.xdata, event.ydata
    else:
        print 'Clicked ouside axes bounds but inside plot window'
fig, ax = plt.subplots()
fig.canvas.callbacks.connect('button_press_event', on_click)
plt.show()

不过,一般来说,看看 matplotlib 在显示、图形、轴和数据坐标之间转换的变换。

例如,event.xdataevent.ydata的等价为:

x, y = event.inaxes.transData.inverted().transform((event.x, event.y))

它有点冗长,但ax.transData是显示(像素(坐标和数据坐标之间的转换。 我们想走另一条路,所以我们用trans.inverted()反转变换。 Transform处理的不仅仅是点(通常你使用它们在另一个坐标系中绘制一些东西(,所以要转换一组点,我们需要调用 transform 方法。

乍一看似乎很麻烦,但实际上相当优雅。所有绘制的艺术家都采用一个transfom参数来定义他们绘制的坐标系。这就是诸如annotate之类的东西允许由数据坐标中另一个位置的偏移量定义的位置的方式。

相关内容

  • 没有找到相关文章

最新更新