Dear All,
I am trying to embed a matplotlib Figure into a Tkinter Canvas. The problem is, when I change the content of the figure (e.g. I delete and create new axes) the new items are plotted but the old items are not deleted. The old items disappear immediately when I resize the window.
I have checked that the elements of Tkinter do their job: the Canvas that contains my figure properly refreshes itself etc, so this is an issue with matplotlib. A similar problem happens indeed using matplotlib with pylab from e.g. ipython -- there one solves the problem by calling the method show() of pylab.figure. In the present case I cannot do that because I have to use matplotlib.figure.Figure instead of matplotlib.figure, and the former lacks the show() method.
I googled a lot for this problem and, while many people discusses refreshing issues, I did not find the solution that I need. Please find below my short code for reference. I may be missing understanding of how this FigureCanvasTkAgg function works: as far as I see, it connects the Canvas of Tkinter (that is the widget in the application) to the real matplotlib.figure.Figure that I want to plot.
Any help will be greatly appreciated.
Best regards,
Andrea
···
################################################################################
# CODE BEGINS
################################################################################
#!/usr/bin/env python
import sys
import numpy as N
import Tkinter
import matplotlib, matplotlib.figure
# Set the backend for matplotlib.
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
class App:
def __init__(self,master):
# Set the properties of the whole window.
master.config(background="gray")
master.wm_title("PaperPlot")
# Create a figure and link it to the Tk canvas.
self.f = matplotlib.figure.Figure(figsize=(3.46, 2.14), frameon=False, dpi=200)
# This canvas links the figure to the Tk canvas.
self.canvas = FigureCanvasTkAgg(self.f, master=master)
self.canvas._tkcanvas.config(background="#c0c0c0", borderwidth=0, highlightthickness=0)
self.canvas.draw()
# The Tk canvas.
self.tkcanvas = self.canvas.get_tk_widget()
self.tkcanvas.pack(fill=Tkinter.X)
# A frame that contains the buttons.
frame0 = Tkinter.Frame(master)
frame0.pack(fill=Tkinter.X, pady=3)
# Buttons.
self.buttonNew = Tkinter.Button(frame0,width=10,text="New",command=self.newPlot)
self.buttonNew.pack(side=Tkinter.LEFT)
self.buttonRun = Tkinter.Button(frame0,width=10,text="Run",command=self.runText)
self.buttonRun.pack(side=Tkinter.LEFT)
self.buttonQuit = Tkinter.Button(frame0,width=10,text='Quit',command=frame0.quit)
self.buttonQuit.pack(side=Tkinter.RIGHT)
self.buttonPrint = Tkinter.Button(frame0,width=10,text="Print",command=self.printPlot)
self.buttonPrint.pack(side=Tkinter.RIGHT)
# A frame that contains the source code of the plot.
frame1 = Tkinter.Frame(master)
frame1.pack(fill=Tkinter.X)
# Text widget with scrollbar that fills the frame and shows the code.
self.scrollbar = Tkinter.Scrollbar(frame1)
self.scrollbar.pack(side=Tkinter.RIGHT, fill=Tkinter.Y)
self.editor = Tkinter.Text(frame1, wrap=Tkinter.WORD, height=20, background="white", yscrollcommand=self.scrollbar.set)
self.editor.pack(fill=Tkinter.X)
self.editor.config(highlightthickness=0)
self.scrollbar.config(command=self.editor.yview)
# Load the file with the source code of the plot.
# theFile = open("plot.py", "r")
# self.editor.insert(Tkinter.END, theFile.read())
# theFile.close()
self.i = 1
def newPlot(self):
self.f.clear()
# HERE SOMETHING IS NEEDED TO FORCE THE FIGURE TO REDRAW!
self.a = self.f.add_axes([0.1*self.i, 0.10*self.i, 0.4, 0.74])
self.i = self.i + 1
self.canvas.draw()
def runText(self):
exec(self.editor.get("0.0", Tkinter.END))
self.canvas.draw()
def printPlot(self):
self.f.savefig("plot.png", dpi=300)
self.f.savefig("plot.pdf")
theText = self.editor.get("0.0", Tkinter.END)
theFile = open("plot.py", "w")
print >> theFile, theText
theFile.close()
# Create the main window of the program.
root = Tkinter.Tk()
# The window is not resizable.
root.resizable(0,0)
# The object that organizes all the widgets and the data in the program.
app = App(root)
# Start the program.
root.mainloop()
################################################################################
# CODE ENDS
################################################################################