【问题标题】:mplcursors not getting generated when used with Tkinter. What am I doing wrong?与 Tkinter 一起使用时不会生成 mplcursors。我究竟做错了什么?
【发布时间】:2019-09-06 12:43:56
【问题描述】:

使用 mplcursors,当 plot matplotlib 嵌入 tkinter gui 时,我无法将光标添加到绘图中。鼠标点击似乎没有注册。但是缩放、平移功能可以正常工作。我错过了什么?

我使用 Anaconda Python 3.7.3、matplotlib 3.0.3 和 mplcursors 库。 https://mplcursors.readthedocs.io/en/stable/#

我可以复制没有 tkinter 的简单示例,并根据需要添加交互式光标。我还可以在 tkinter 应用程序中嵌入 matplotlib 图。但是,当两者结合时 - 即使绘图显示没有错误,交互式光标也不起作用。

import tkinter

from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler
import matplotlib.pyplot as plt

import numpy as np
import mplcursors


root = tkinter.Tk()
root.wm_title("Embedding in Tk")


t = np.arange(0, 3, .01)

fig, ax = plt.subplots(1, 1)
line = ax.plot(t, 2 * np.sin(2 * np.pi * t))

mplcursors.cursor(line)

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)

toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)


def on_key_press(event):
    print("you pressed {}".format(event.key))
    key_press_handler(event, canvas, toolbar)


canvas.mpl_connect("key_press_event", on_key_press)


def _quit():
    root.quit()
    root.destroy()  

button = tkinter.Button(master=root, text="Quit", command=_quit)
button.pack(side=tkinter.BOTTOM)

tkinter.mainloop()

我应该能够在没有 tkinter 的情况下像示例中一样添加和操作光标。

【问题讨论】:

  • 问题来自pyplot的使用。从embedding in tk example可以看出,嵌入时不应该使用pyplot。
  • 我也用图试了一下,结果一样。

标签: python matplotlib tkinter interactive mplcursors


【解决方案1】:

两个问题:

  1. 在 GUI 中嵌入 matplotlib 时不应使用 pyplot。请参阅embedding in tk example
  2. mplcursors 需要使用图形画布。所以它只能在画布被定义后使用。所以代码线需要在定义FigureCanvasTkAgg之后出现。

完整代码:

import tkinter

from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure

import numpy as np
import mplcursors


root = tkinter.Tk()
root.wm_title("Embedding in Tk")


t = np.arange(0, 3, .01)

fig = Figure()
ax = fig.add_subplot(111)
line = ax.plot(t, 2 * np.sin(2 * np.pi * t))

canvas = FigureCanvasTkAgg(fig, master=root)

mplcursors.cursor(line)

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

toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)


def on_key_press(event):
    print("you pressed {}".format(event.key))
    key_press_handler(event, canvas, toolbar)


canvas.mpl_connect("key_press_event", on_key_press)


def _quit():
    root.quit()
    root.destroy()  

button = tkinter.Button(master=root, text="Quit", command=_quit)
button.pack(side=tkinter.BOTTOM)

tkinter.mainloop()

【讨论】:

  • 就是这样。在这些更改之后,我的示例代码起作用了。但是,当我使用网格布局和启用工具栏时,我的主要代码遇到了其他问题。虽然绘图是可见的,并且工具栏功能正在工作,但单击绘图添加光标会使 Python 停止工作。使用包布局它可以工作。如果有人遇到类似问题,就把它扔掉。
  • 该示例甚至可以使用 pyplot。看起来真正的问题是上面第 2 点中提到的 - mplcursors 需要与图形画布一起使用。所以它只能在画布被定义后使用。所以代码线需要在定义 FigureCanvasTkAgg 之后出现
  • 仅仅因为某些东西有效,并不意味着它应该被使用。如果一开始这里没有使用 pyplot,代码会直接抛出错误,导致 undefined canvas 的问题。
猜你喜欢
  • 2019-09-08
  • 2013-08-06
  • 1970-01-01
  • 2019-05-26
  • 1970-01-01
  • 2016-05-27
  • 2016-07-18
  • 1970-01-01
  • 2019-12-23
相关资源
最近更新 更多