title: Matplotlib plot in Tkinter - every update adds new NavigationToolbar?
body: <p>I am working on a Tkinter-GUI to interactively generate Matplotlib-plots, depending on user-input. For this end, it needs to re-plot after the user changes the input.</p>
  
  <p>I have gotten it to work in principle, but would like to include the <code>NavigationToolbar</code>. However, I cannot seem to get the updating of the <code>NavigationToolbar</code> to work correctly.</p>
  
  <p>Here is a basic working version of the code (without the user input Entries):</p>
  
  <pre><code># Import modules
  from Tkinter import *
  import numpy as np
  import matplotlib.pyplot as plt
  from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
  
  # global variable: do we already have a plot displayed?
  show_plot = False
  
  # plotting function
  def plot(x, y):
      fig = plt.figure()
      ax1 = fig.add_subplot(1,1,1)
      ax1.plot(x,y)
      return fig
  
  def main():
      x = np.arange(0.0,3.0,0.01)
      y = np.sin(2*np.pi*x)
      fig = plot(x, y)
  
      canvas = FigureCanvasTkAgg(fig, master=root)
      toolbar = NavigationToolbar2TkAgg(canvas, toolbar_frame)
  
      global show_plot
      if show_plot:
          #remove existing plot and toolbar widgets
          canvas.get_tk_widget().grid_forget()
          toolbar_frame.grid_forget()
  
      toolbar_frame.grid(row=1,column=1)
      canvas.get_tk_widget().grid(row=0,column=1)
      show_plot=True
  
  # GUI
  root = Tk()
  
  draw_button = Button(root, text="Plot!", command = main)
  draw_button.grid(row=0, column=0)
  
  fig = plt.figure()
  canvas = FigureCanvasTkAgg(fig, master=root)
  canvas.get_tk_widget().grid(row=0,column=1)
  toolbar_frame = Frame(root)
  toolbar_frame.grid(row=1,column=1)
  
  root.mainloop()
  </code></pre>
  
  <p>Pressing "Plot!" <em>once</em> generates the plot and the <code>NavigationToolbar</code>.
  Pressing it a second time replots, but generates a <em>second</em> <code>NavigationToolbar</code> (and another every time "Plot!" is pressed). Which sounds like <code>grid_forget()</code> is not working.
  However, when I change</p>
  
  <pre><code>    if show_plot:
          #remove existing plot and toolbar widgets
          canvas.get_tk_widget().grid_forget()
          toolbar_frame.grid_forget()
  
      toolbar_frame.grid(row=1,column=1)
      canvas.get_tk_widget().grid(row=0,column=1)
      show_plot=True
  </code></pre>
  
  <p>to</p>
  
  <pre><code>    if show_plot:
          #remove existing plot and toolbar widgets
          canvas.get_tk_widget().grid_forget()
          toolbar_frame.grid_forget()
      else:
          toolbar_frame.grid(row=1,column=1)
      canvas.get_tk_widget().grid(row=0,column=1)
      show_plot=True
  </code></pre>
  
  <p>then the <code>NavigationToolbar</code> <em>does</em> vanish when "Plot!" is pressed a second time (but then there is, as expected, no new <code>NavigationToolbar</code> to replace the old). So <code>grid_forget()</code> <em>is</em> working, just not as expected.</p>
  
  <p>What am I doing wrong? Is there a better way to update the <code>NavigationToolbar</code>?</p>
  
  <p>Any help greatly appreciated!
  Lastalda</p>
  
  <p><strong>Edit:</strong></p>
  
  <p>I found that this will work if you destroy the NavigationToolbar instead of forgetting it. But you have to completely re-create the widget again afterwards, of course:</p>
  
  <pre><code>canvas = FigureCanvasTkAgg(fig, master=root)
  toolbar_frame = Frame(root)
  
  global show_plot
  if show_plot: # if plot already present, remove plot and destroy NavigationToolbar
  
      canvas.get_tk_widget().grid_forget()
      toolbar_frame.destroy()
  
  toolbar_frame = Frame(root)
  toolbar = NavigationToolbar2TkAgg(canvas, toolbar_frame)
  toolbar_frame.grid(row=21,column=4,columnspan=3)
  canvas.get_tk_widget().grid(row=1,column=4,columnspan=3,rowspan=20)
  
  show_plot = True
  </code></pre>
  
  <p>However, the updating approach showed by Hans below is much nicer since you don't have to destroy and recreate anything. I just wanted to highlight that the issue with my approach (apart from the inelegance and performance) was probably that I didn't use <code>destroy()</code>.</p>