|
From: Vlastimil B. <vla...@gm...> - 2012-11-02 11:01:43
|
2012/11/1 Hans Bering <han...@ar...>: > Hello everybody, > > I'm building a small Tkinter GUI using matplotlib, in which I have to > change/update plots quite often depending on user input (with different > contents & sizes, in different places in the GUI, etc.; but always only > one figure at a time). > > As a first resort, I regenerated the figures with plt.figure(...) whenever > necessary; unfortunately, the program happily accumulated memory with > every new figure until the computer would no longer cooperate in a timely > fashion. The following minimal script should demonstrate the tendency: > ... > Now I am wondering if I am missing some detail, e.g., some other clean-up > procedure? Or should this work & could be a memory leak in matplotlib or > Tkinter? And/or is this approach (of generating a new figure every time) > not recommended in the first place? I tried reusing the figure, but some > aspects like changing the layout in the GUI and applying new size and dpi > then proved tricky in their own ways. > > Many thanks in advance, > Hans > Hi, I'd recommend to use an embedded plot and only clear and replace its content (rather than tu use pyplot and recreate the figure multiple times. I believe, changing of the figure should be possible too. see e.g. the sample for tkinter http://matplotlib.org/examples/user_interfaces/embedding_in_tk.html I only roughly adapted that source to use your function and the memory usage appears to be more effective (although there is some increase too - as displayed in Process Explorer). Would some variation of the following work for you? hth, vbr ######################################## #!/usr/bin/env python import matplotlib matplotlib.use('TkAgg') import math from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg from matplotlib.figure import Figure import Tkinter root = Tkinter.Tk() root.wm_title("Embedding in TK") fig = Figure(figsize=(5,4), dpi=100) ax = fig.add_subplot(111) canvas = FigureCanvasTkAgg(fig, master=root) canvas.show() canvas.get_tk_widget().pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1) toolbar = NavigationToolbar2TkAgg( canvas, root ) toolbar.update() canvas._tkcanvas.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1) plotShift = 0 def replot(): global plotShift, a, f ax.clear() xVals = xrange(100) ax.plot(xVals, [math.sin(x + plotShift) for x in xVals]) fig.canvas.draw() plotShift += 10 button = Tkinter.Button(master=root, text='replot', command=replot) button.pack(side=Tkinter.BOTTOM) Tkinter.mainloop() |