Sirius
Sirius

Reputation: 58

mplcursors not getting generated when used with Tkinter. What am I doing wrong?

Using mplcursors, I'm not able to add cursors to the plot when plot matplotlib is embedded in tkinter gui. It appears that mouse clicks are not registering. However zoom, pan functions work fine. What am I missing?

I use Anaconda Python 3.7.3, matplotlib 3.0.3, and mplcursors library. https://mplcursors.readthedocs.io/en/stable/#

I am able replicate simple example without tkinter and add interactive cursors as needed. I am also able to embed matplotlib plot in tkinter application. However when both are combined - even though plot is shown without errors, interactive cursors are not working.

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()

I should be able to add and manipulate cursors like in example without tkinter.

Upvotes: 0

Views: 1902

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339120

Two problems:

  1. You should not use pyplot when embedding matplotlib in GUIs. Refer to the embedding in tk example.
  2. mplcursors needs to work with the figure canvas. So it can only be used once the canvas is defined. So that codeline needs to come after defining FigureCanvasTkAgg.

Complete code:

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()

Upvotes: 1

Related Questions