I am trying to update the data in a matplotlib imshow window within a Tkinter gui, an example of my code is as follows:
#minimal example...
import matplotlib, sys
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import pylab as plt
from scipy import ndimage
if sys.version_info[0] < 3:
import Tkinter as Tk
else:
import tkinter as Tk
root = Tk.Tk()
root.wm_title("minimal example")
image = plt.imread('test.jpg')
fig = plt.figure(figsize=(5,4))
im = plt.imshow(image) # later use a.set_data(new_data)
ax = plt.gca()
ax.set_xticklabels([])
ax.set_yticklabels([])
# a tk.DrawingArea
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.show()
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
def rotate(*args):
print 'rotate button press...'
theta = 90
rotated = ndimage.rotate(image, theta)
im.set_data(rotated)
root.update()
def quit(*args):
print 'quit button press...'
root.quit()
root.destroy()
button_rotate = Tk.Button(master = root, text = 'Rotate', command = rotate)
button_quit = Tk.Button(master = root, text = 'Quit', command = quit)
button_quit.pack(side=Tk.LEFT)
button_rotate.pack()
Tk.mainloop()
As you can see, I load an image using imshow(), and then try updating the image's data using set_data(), and then want to update the root window of the gui using root.update(). When executed, the print 'rotate button press...' line is executed, but the rest is seemingly not. Do I need to pass the image handle to the rotate function some how, or return the rotated image?
1 Answer 1
The canvas needs to be redrawn, try this:
def rotate(*args):
print 'rotate button press...'
theta = 90
rotated = ndimage.rotate(image, theta)
im.set_data(rotated)
canvas.draw()
Update to keep rotating
Note this is saving image
as an attribute of root
. Maybe not the best approach but it works for the example.
root = Tk.Tk()
root.wm_title("minimal example")
root.image = plt.imread('test.jpg')
fig = plt.figure(figsize=(5,4))
im = plt.imshow(root.image) # later use a.set_data(new_data)
ax = plt.gca()
ax.set_xticklabels([])
ax.set_yticklabels([])
# a tk.DrawingArea
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.show()
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
def rotate(*args):
print 'rotate button press...'
root.image = ndimage.rotate(root.image, 90)
im.set_data(root.image)
canvas.draw()
3 Comments
image
90 degrees. I'll update with another fix, but you'd be better off refactoring to make your own subclass of Tkinter.Frame so you can save your application's attributes...but that's for another question.pyplot
while embedding.
pyplot
if you are embedding. You end up with dueling gui main loops.pylot
, how can I accessimshow()
?