I have the following code that simply embeds a matplotlib plot inside a tab in tkinter, then connects an onclick event for any mouse click to print some data:
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
import numpy as np
def onclick(event):
print('%s click: button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %
('double' if event.dblclick else 'single', event.button,
event.x, event.y, event.xdata, event.ydata))
root = tk.Tk()
root.wm_title("Embedding in Tk")
tabs = ttk.Notebook(root)
tab = ttk.Frame(tabs)
fig = Figure(figsize=(5, 4), dpi=100)
t = np.arange(0, 3, .01)
ax = fig.add_subplot(111)
ax.plot(t, 2 * np.sin(2 * np.pi * t))
canvas = FigureCanvasTkAgg(fig, master=tab)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
tabs.add(tab, text="Tab one")
tabs.pack(expand=1, fill='both')
fig.canvas.mpl_connect("button_press_event", onclick)
root.mainloop()
Which all works fine, however if the line fig.canvas.mpl_connect("button_press_event", onclick) is placed after the root.mainloop() line, the clicking function no longer works on the embedded tab. I wanted to know why this is. Below is the code that reproduces the issue:
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
import numpy as np
def onclick(event):
print('%s click: button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %
('double' if event.dblclick else 'single', event.button,
event.x, event.y, event.xdata, event.ydata))
root = tk.Tk()
root.wm_title("Embedding in Tk")
tabs = ttk.Notebook(root)
tab = ttk.Frame(tabs)
fig = Figure(figsize=(5, 4), dpi=100)
t = np.arange(0, 3, .01)
ax = fig.add_subplot(111)
ax.plot(t, 2 * np.sin(2 * np.pi * t))
canvas = FigureCanvasTkAgg(fig, master=tab)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
tabs.add(tab, text="Tab one")
tabs.pack(expand=1, fill='both')
root.mainloop()
fig.canvas.mpl_connect("button_press_event", onclick)
The part that confuses me is I went out of my way to create a realistic example of when the fig.canvas.mpl_connect("button_press_event", onclick) might be placed after the root.mainloop() , and wrote this:
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
import numpy as np
def onclick(event):
print('%s click: button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %
('double' if event.dblclick else 'single', event.button,
event.x, event.y, event.xdata, event.ydata))
def open_plot():
tab = ttk.Frame(tabs)
fig = Figure(figsize=(5, 4), dpi=100)
t = np.arange(0, 3, .01)
ax = fig.add_subplot(111)
ax.plot(t, 2 * np.sin(2 * np.pi * t))
canvas = FigureCanvasTkAgg(fig, master=tab)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
tabs.add(tab, text="Tab one")
tabs.pack(expand=1, fill='both')
fig.canvas.mpl_connect("button_press_event", onclick)
root = tk.Tk()
root.wm_title("Embedding in Tk")
tabs = ttk.Notebook(root)
menubar = tk.Menu(root)
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Open", command=open_plot)
menubar.add_cascade(label="File", menu=filemenu)
root.config(menu=menubar)
root.mainloop()
But in this example, the onclick function now works again as expected. Would anyone be able to explain why this is?