问题
I am trying to create a Tkinter widget class that embeds a matplotlib graph in a canvas object. The code I have written almost works but doesn't seem to exit properly when the widget is closed. Here is the code I am using. This is not the actual matplotlib graph code I am using but something I wrote for the purpose of asking this question. My original matplotlib graph code is very long and is too impractical to try and copy for this post.
from Tkinter import *
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
def schart2(stock_sym):
x = [1,2,3,4]
y = [20,21,20.5, 20.8]
plt.plot(x,y)
plt.show()
class StockChart(Frame):
def __init__(self, stock_sym=''):
Frame.__init__(self, parent=None)
self.pack(expand=YES, fill=BOTH)
self.makeWidgets(stock_sym)
def makeWidgets(self, stock_sym):
#self.f = graphData(stock_sym,12,26)
self.f = schart2(stock_sym)
self.canvas = FigureCanvasTkAgg(self.f)
self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
self.canvas.show()
if __name__ == '__main__':
StockChart('ACAD').mainloop()
When I run this code the widget is properly drawn and behaves as expected, but when I click the close icon button the widget disappears from the screen but the code continues to run and the idle prompt never reappears, instead the idle prompt just has a flashing cursor but no prompt. Normally when I create a widget like this, when I click the close icon button the widget closes and the underlying code also exits returning me to the normal idle prompt. If anyone has any ideas on how to get this code to exit properly I would appreciate the help. I am assuming that the problem is somehow related to the portion of the code which does the matplotlib embedding. Sincerely, George
回答1:
You're not accessing Tkinter at all using this code, because your function schart2 returns None
, which is then assigned to self.f
and used for self.canvas = FigureCanvasTkAgg(self.f)
.
Rather, the window you're getting is from Matplotlib - the plt.plot
and plt.show
commands pop up a pure matplotlib figure.
To get an embedded figure in Tkinter the way you want, all you have to do is re-do schart2 to return a figure, and don't use pyplot:
def schart2(stock_sym):
x = [1,2,3,4]
y = [20,21,20.5, 20.8]
fig = Figure()
axes = fig.add_subplot(111)
axes.plot(x,y)
return fig
In addition:
You'll also want to remove the self.canvas.show()
, because it causes a Tkinter error about an 'update_idletasks' attribute, but I'm not enough of a Tkinter expert to figure that one out, plus it's a separate question (there are already a few discussions on SO). There is also a namespace issue - take the Tk.
off of side=Tk.TOP, fill=Tk.BOTH
, because you've done from Tkinter import *
.
来源:https://stackoverflow.com/questions/27546777/embedding-a-matplotlib-graph-in-a-tkinter-canvas-widget-class