嵌入 Tkinter 时未调用 Matplotlib 事件处理程序

Matplotlib Event Handlers not being Called when Embedded in Tkinter

概述

我正在将 Matplotlib 图嵌入 Tkinter window。我需要使用 Matplotlib 事件处理函数(描述 here)。当 运行 作为独立的 Matplotlib 图时,我得到了正确的行为:事件处理程序对正确的用户操作执行正确的功能。但是当嵌入到 Tkinter 中时 window,Matplotlib 事件处理程序不再被调用。

预期行为

当图形嵌入到 Tkinter 中时,应调用 Matplotlib 事件处理程序 window。

当前行为

未调用 Matplotlib 事件处理程序。

最小代码片段

没有 Tkinter

import matplotlib.pyplot as plt

def onpick(event):
    print("You selected the line!")

if __name__=='__main__':
    ### MATPLOTLIB SETUP ###
    xs = [0,1,2] #x-values of the graph
    ys = [4,3,2] #y-values of the graph

    fig, ax = plt.subplots(1)
    ax.plot(xs, ys, picker=True)
    fig.canvas.mpl_connect('pick_event', onpick)

    plt.show()

当此代码为 运行 时,您可以 select 绘图上的线条并调用 onpick 方法,将文本打印到 stdout。这是所需的输出。

嵌入 Tkinter

import tkinter
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt

def onpick(event):
    print("You selected the line!")

if __name__=='__main__':
    ### MATPLOTLIB SETUP ###
    xs = [0,1,2] #x-values of the graph
    ys = [4,3,2] #y-values of the graph

    fig, ax = plt.subplots(1)
    ax.plot(xs, ys, picker=True)
    fig.canvas.mpl_connect('pick_event', onpick)

    ### TKINTER SETUP ###

    root = tkinter.Tk()
    canvas = FigureCanvasTkAgg(fig, master=root)
    canvas.draw()

    canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
    
    tkinter.mainloop()
    

当此代码为 运行 并且您尝试单击该行时,永远不会打印文本,这意味着永远不会调用 onpick 方法。

版本

Matplotlib Figure对象的事件监听器嵌入到Tkinter中时无法调用。相反,您必须将侦听器添加到 FigureCanvasTkAgg(或类似的)对象。因此,一个基于前面最小示例的工作示例将是:

import tkinter
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt

def onpick(event):
    print("You selected the line!")

if __name__=='__main__':
    ### MATPLOTLIB SETUP ###
    xs = [0,1,2] #x-values of the graph
    ys = [4,3,2] #y-values of the graph

    fig, ax = plt.subplots(1)
    ax.plot(xs, ys, picker=True)

    #plt.show()

    ### TKINTER SETUP ###

    root = tkinter.Tk()
    canvas = FigureCanvasTkAgg(fig, master=root)
    canvas.draw()

    canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)

    canvas.mpl_connect("pick_event", onpick) # Add the listener using this command

    tkinter.mainloop()