From 77d9500dcec7bc6a6a9d169f0649b09c4da38f86 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Mon, 2 Oct 2017 00:58:01 -0700 Subject: [PATCH 1/4] Fix tkagg animation error at exit. Apparently, with a small enough animation interval, tk does not have the time to fully proceed through FigureManagerTkAgg.show before the animation takes over. Removing the call to self.window.update (which had been added back in 2004 (6c96389), but seems unnecessary (including on Windows)) fixes the issue. Also update the animation example so that it can serve as manual test for the issue; changed the rate at which the data moves to keep it reasonable, and switched to None (= count()) as index iterable to avoid a jump every time we reach the end of the indices. --- examples/animation/simple_anim.py | 6 +++--- lib/matplotlib/backends/backend_tkagg.py | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/animation/simple_anim.py b/examples/animation/simple_anim.py index 417aa5f36709..457bfba12fed 100644 --- a/examples/animation/simple_anim.py +++ b/examples/animation/simple_anim.py @@ -16,7 +16,7 @@ def animate(i): - line.set_ydata(np.sin(x + i/10.0)) # update the data + line.set_ydata(np.sin(x + i / 100)) # update the data return line, @@ -25,6 +25,6 @@ def init(): line.set_ydata(np.ma.array(x, mask=True)) return line, -ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), init_func=init, - interval=25, blit=True) +ani = animation.FuncAnimation( + fig, animate, init_func=init, interval=2, blit=True) plt.show() diff --git a/lib/matplotlib/backends/backend_tkagg.py b/lib/matplotlib/backends/backend_tkagg.py index 85d32067f4e2..95ce8ccafc1e 100644 --- a/lib/matplotlib/backends/backend_tkagg.py +++ b/lib/matplotlib/backends/backend_tkagg.py @@ -555,8 +555,6 @@ def destroy(*args): Gcf.destroy(self._num) self.canvas._tkcanvas.bind("", destroy) self.window.deiconify() - # anim.py requires this - self.window.update() else: self.canvas.draw_idle() # Raise the new window. From 87fde92b8556ca781cdd2c5de0bcc368ff38b90f Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 3 Oct 2017 10:12:52 -0700 Subject: [PATCH 2/4] Deprecate passing event to FigureManagerTkAgg.resize. --- lib/matplotlib/backends/backend_tkagg.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/matplotlib/backends/backend_tkagg.py b/lib/matplotlib/backends/backend_tkagg.py index 95ce8ccafc1e..91a353826458 100644 --- a/lib/matplotlib/backends/backend_tkagg.py +++ b/lib/matplotlib/backends/backend_tkagg.py @@ -536,6 +536,8 @@ def resize(self, width, height=None): # when a single parameter is given, consider it as a event if height is None: + cbook.warn_deprecated("2.2", "FigureManagerTkAgg.resize now takes " + "width and height as separate arguments") width = width.width else: self.canvas._tkcanvas.master.geometry("%dx%d" % (width, height)) From f56e0013e72ddfb81d6bdfb1fdb41ea1e493b0e0 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 3 Oct 2017 10:37:15 -0700 Subject: [PATCH 3/4] Deprecate FigureCanvasTkAgg.show in favor of .draw. This provides the same method name as in the other backends. --- .../user_interfaces/embedding_in_tk2_sgskip.py | 2 +- examples/user_interfaces/embedding_in_tk_sgskip.py | 2 +- lib/matplotlib/backends/backend_tkagg.py | 14 ++++++++------ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/examples/user_interfaces/embedding_in_tk2_sgskip.py b/examples/user_interfaces/embedding_in_tk2_sgskip.py index 89be179d4058..ed3c5f1357a5 100644 --- a/examples/user_interfaces/embedding_in_tk2_sgskip.py +++ b/examples/user_interfaces/embedding_in_tk2_sgskip.py @@ -38,7 +38,7 @@ def destroy(e): # a tk.DrawingArea canvas = FigureCanvasTkAgg(f, master=root) -canvas.show() +canvas.draw() canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) diff --git a/examples/user_interfaces/embedding_in_tk_sgskip.py b/examples/user_interfaces/embedding_in_tk_sgskip.py index 8def18952312..b4ea1669c356 100644 --- a/examples/user_interfaces/embedding_in_tk_sgskip.py +++ b/examples/user_interfaces/embedding_in_tk_sgskip.py @@ -35,7 +35,7 @@ # a tk.DrawingArea canvas = FigureCanvasTkAgg(f, master=root) -canvas.show() +canvas.draw() canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) toolbar = NavigationToolbar2TkAgg(canvas, root) diff --git a/lib/matplotlib/backends/backend_tkagg.py b/lib/matplotlib/backends/backend_tkagg.py index 91a353826458..7a36dc6febd4 100644 --- a/lib/matplotlib/backends/backend_tkagg.py +++ b/lib/matplotlib/backends/backend_tkagg.py @@ -231,7 +231,7 @@ def resize(self, event): master=self._tkcanvas, width=int(width), height=int(height)) self._tkcanvas.create_image(int(width/2),int(height/2),image=self._tkphoto) self.resize_event() - self.show() + self.draw() # a resizing will in general move the pointer position # relative to the canvas, so process it as a motion notify @@ -307,10 +307,12 @@ def draw(self): self._master.update_idletasks() def blit(self, bbox=None): - tkagg.blit(self._tkphoto, self.renderer._renderer, bbox=bbox, colormode=2) + tkagg.blit( + self._tkphoto, self.renderer._renderer, bbox=bbox, colormode=2) self._master.update_idletasks() - show = draw + show = cbook.deprecated("2.2", name="FigureCanvasTkAgg.show", + alternative="FigureCanvasTkAgg.draw")(draw) def draw_idle(self): 'update drawing area only if idle' @@ -738,8 +740,8 @@ def configure_subplots(self): window = Tk.Toplevel() canvas = FigureCanvasTkAgg(toolfig, master=window) toolfig.subplots_adjust(top=0.9) - canvas.tool = SubplotTool(self.canvas.figure, toolfig) - canvas.show() + canvas.tool = SubplotTool(self.canvas.figure, toolfig) + canvas.draw() canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) window.grab_set() @@ -1021,7 +1023,7 @@ def init_window(self): canvas = FigureCanvasTkAgg(toolfig, master=self.window) toolfig.subplots_adjust(top=0.9) _tool = SubplotTool(self.figure, toolfig) - canvas.show() + canvas.draw() canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.window.protocol("WM_DELETE_WINDOW", self.destroy) From 2597f3deace4fbea6d755f3b440935c8041832fd Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 3 Oct 2017 10:43:15 -0700 Subject: [PATCH 4/4] Cleanup embedding_in_tk, remove embedding_in_tk2. embedding_in_tk2_sgskip is essentially a slightly simplified duplicate of embedding_in_tk_sgskip. --- .../embedding_in_tk2_sgskip.py | 49 ------------------- .../user_interfaces/embedding_in_tk_sgskip.py | 49 ++++++++----------- 2 files changed, 20 insertions(+), 78 deletions(-) delete mode 100644 examples/user_interfaces/embedding_in_tk2_sgskip.py diff --git a/examples/user_interfaces/embedding_in_tk2_sgskip.py b/examples/user_interfaces/embedding_in_tk2_sgskip.py deleted file mode 100644 index ed3c5f1357a5..000000000000 --- a/examples/user_interfaces/embedding_in_tk2_sgskip.py +++ /dev/null @@ -1,49 +0,0 @@ -""" -================ -Embedding In Tk2 -================ - -""" -import matplotlib -matplotlib.use('TkAgg') - -from numpy import arange, sin, pi -from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg -from matplotlib.figure import Figure - -import sys -if sys.version_info[0] < 3: - import Tkinter as Tk -else: - import tkinter as Tk - - -def destroy(e): - sys.exit() - -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) -a.set_title('Tk embedding') -a.set_xlabel('X axis label') -a.set_ylabel('Y label') - - -# a tk.DrawingArea -canvas = FigureCanvasTkAgg(f, master=root) -canvas.draw() -canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) - -canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) - -button = Tk.Button(master=root, text='Quit', command=sys.exit) -button.pack(side=Tk.BOTTOM) - -Tk.mainloop() diff --git a/examples/user_interfaces/embedding_in_tk_sgskip.py b/examples/user_interfaces/embedding_in_tk_sgskip.py index b4ea1669c356..bee6bb050281 100644 --- a/examples/user_interfaces/embedding_in_tk_sgskip.py +++ b/examples/user_interfaces/embedding_in_tk_sgskip.py @@ -4,37 +4,26 @@ =============== """ -import matplotlib -matplotlib.use('TkAgg') - -from numpy import arange, sin, pi -from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg -# implement the default mpl key bindings -from matplotlib.backend_bases import key_press_handler +from six.moves import tkinter as Tk +from matplotlib.backends.backend_tkagg import ( + FigureCanvasTkAgg, NavigationToolbar2TkAgg) +# Implement the default Matplotlib key bindings. +from matplotlib.backend_bases import key_press_handler 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") +import numpy as np -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) +root = Tk.Tk() +root.wm_title("Embedding in Tk") +fig = Figure(figsize=(5, 4), dpi=100) +t = np.arange(0, 3, .01) +fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t)) -# a tk.DrawingArea -canvas = FigureCanvasTkAgg(f, master=root) +canvas = FigureCanvasTkAgg(fig, master=root) # A tk.DrawingArea. canvas.draw() canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) @@ -43,11 +32,12 @@ canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) -def on_key_event(event): - print('you pressed %s' % event.key) +def on_key_press(event): + print("you pressed {}".format(event.key)) key_press_handler(event, canvas, toolbar) -canvas.mpl_connect('key_press_event', on_key_event) + +canvas.mpl_connect("key_press_event", on_key_press) def _quit(): @@ -55,9 +45,10 @@ def _quit(): 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 = Tk.Button(master=root, text="Quit", command=_quit) button.pack(side=Tk.BOTTOM) Tk.mainloop() -# If you put root.destroy() here, it will cause an error if -# the window is closed with the window manager. +# If you put root.destroy() here, it will cause an error if the window is +# closed with the window manager.