alessandro
alessandro

Reputation: 3984

tkinter with matplotlib

I read it is possible to embed a pyplot in tkinter, but I'm having a problem:

I need to display some frames, among which a pyplot in a frame of the main Tkinter window, and it has to react to my keypresses.

According to http://matplotlib.org/examples/user_interfaces/embedding_in_tk.html this works:

#!/usr/bin/env python
from Tkinter import *
import matplotlib
matplotlib.use('TkAgg')    
from numpy import arange, sin, pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
import matplotlib.backend_bases       
from matplotlib.figure import Figure    
import sys
if sys.version_info[0] < 3:
    import Tkinter as Tk
else:
    import tkinter as Tk

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


f = Figure(figsize=(5,4), dpi=100)
a = f.add_subplot(111)
t = arange(0.0,3.0,0.01)
s = sin(2*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._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

def on_key_event(event):
    print('you pressed %s'%event.key)

canvas.mpl_connect('key_press_event', on_key_event)

def _quit():
    root.quit()     # stops mainloop
    root.destroy()  # this is necessary on Windows to prevent
                    # Fatal Python Error: PyEval_RestoreThread: NULL tstate

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

Tk.mainloop()

And I was happy... but if I try, as an example, to have a Text frame on top of it:

t=Text(root)
t.pack()

(before the canvas variable definition) as soon as I click on the Text frame & write into it, there is no way to click on the pyplot window and make it catch my keypresses again!

Any hints?

Upvotes: 7

Views: 3676

Answers (1)

FabienAndre
FabienAndre

Reputation: 4603

In tkinter, key events are routed to the widget that get the focus, thus your problem is to set focus back to the canvas. This is possible through binding on click on canvas to set the focus.

For instance:

canvas.mpl_connect('button_press_event', lambda event:canvas._tkcanvas.focus_set())
#or canvas._tkcanvas.bind('<Button1>', ...)

Upvotes: 7

Related Questions