问题
I can't understand how to refresh FigureCanvasWxAgg instance. Here is the example:
import wx
import matplotlib
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.NewId(), "Main")
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.figure = Figure(figsize=(1,2))
self.axe = self.figure.add_subplot(111)
self.figurecanvas = FigureCanvas(self, -1, self.figure)
self.buttonPlot = wx.Button(self, wx.NewId(), "Plot")
self.buttonClear = wx.Button(self, wx.NewId(), "Clear")
self.sizer.Add(self.figurecanvas, proportion=1, border=5, flag=wx.ALL | wx.EXPAND)
self.sizer.Add(self.buttonPlot, proportion=0, border=2, flag=wx.ALL)
self.sizer.Add(self.buttonClear, proportion=0, border=2, flag=wx.ALL)
self.SetSizer(self.sizer)
self.figurecanvas.Bind(wx.EVT_LEFT_DCLICK, self.on_dclick)
self.buttonPlot.Bind(wx.EVT_BUTTON, self.on_button_plot)
self.buttonClear.Bind(wx.EVT_BUTTON, self.on_button_clear)
self.subframe_opened = False
def on_dclick(self, evt):
self.subframe = SubFrame(self, self.figure)
self.subframe.Show(True)
self.subframe_opened = True
def on_button_plot(self, evt):
self.axe.plot(range(10), color='green')
self.figurecanvas.draw()
def on_button_clear(self, evt):
if self.subframe_opened:
self.subframe.Close()
self.figure.set_canvas(self.figurecanvas)
self.axe.clear()
self.figurecanvas.draw()
class SubFrame(wx.Frame):
def __init__(self, parent, figure):
wx.Frame.__init__(self, parent, wx.NewId(), "Sub")
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.figurecanvas = FigureCanvas(self, -1, figure)
self.sizer.Add(self.figurecanvas, proportion=1, border=5, flag=wx.ALL | wx.EXPAND)
self.SetSizer(self.sizer)
self.Bind(wx.EVT_CLOSE, self.on_close)
def on_close(self, evt):
self.GetParent().subframe_opened = False
evt.Skip()
class MyApp(wx.App):
def OnInit(self):
frame = MainFrame()
frame.Show(True)
self.SetTopWindow(frame)
return True
app = MyApp(0)
app.MainLoop()
I'm interested in the following sequence of operations:
- run a script
- resize the main frame
- press Plot button
- double click on plot
- press Clear button
Now I get a mess on main frame plot. If I resize the frame it redraws properly. My question is what should I add to my code to do that without resizing?
By a "mess" I mean something like this:
http://img227.imageshack.us/img227/5407/mess.png
Thanks in advance.
回答1:
As I said in the comments, I don't think that the figure canvas refresh is your problem, in fact I think it's doing exactly what it's supposed to (redrawing itself based on it's last state [ie as it was in your subplot]). I think your problem is more that the wxFrame is not refreshing.
The easiest way to fix that would be to make it resize itself on your "Clear" event. Something like:
def on_button_clear(self, evt):
if self.subframe_opened:
self.subframe.Close()
self.figure.set_canvas(self.figurecanvas)
self.axe.clear()
self.figurecanvas.draw()
self.SetSize((self.Size[0],self.figurecanvas.Size[1]))
The set size would cause the frame and all the controls it contains to be redrawn.
That said, I think sharing your figure between the two figurecanvas is dangerous. I was able to produce some serious errors by clicking/resizing things in different combinations. On occasion your figure would be garbage collected when the subframe was closed, making it unavailable to your main frame.
来源:https://stackoverflow.com/questions/2441906/matplotlib-how-to-refresh-figure-canvas