2010-03-14 8 views
11

No puedo entender cómo actualizar la instancia de FigureCanvasWxAgg. Aquí está el ejemplo:matplotlib: cómo actualizar figure.canvas


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()  

Estoy interesado en la siguiente secuencia de operaciones:

  • ejecutar un script
  • cambiar el tamaño del marco principal
  • pulse el botón Plot
  • doble clic en la parcela
  • pulse el botón Borrar

Ahora me da un lío en el diagrama de fotograma principal. Si cambio el tamaño del cuadro, se vuelve a dibujar correctamente. Mi pregunta es, ¿qué debería agregar a mi código para hacer eso sin cambiar el tamaño?

Por un "desorden" me refiero a algo como esto:

http://img227.imageshack.us/img227/5407/mess.png

Gracias de antemano.

+0

@Alex, no estoy seguro de lo que estás preguntando, ¿qué quieres decir con un "desastre"? Probé tu código y no veo ningún problema. El fotograma principal cambia el tamaño de forma correcta, el botón dibuja el gráfico, hace doble clic crea un nuevo fotograma que muestra el mismo lienzo de figura que el principal, el botón borrar borra el gráfico y cierra el fotograma secundario. – Mark

+0

Hmm ... eso es raro, agregué la imagen con el estado después de Borrar. – Alex

+0

Intenté originalmente en Linux, en Windows puedo reproducir su imagen. Es porque estás compartiendo tu objeto figura entre los dos marcos wx (probablemente no es una buena idea). Si nadie me lo pide, lo miraré más de cerca esta noche. – Mark

Respuesta

11

Como dije en los comentarios, no creo que la actualización del lienzo de la figura sea su problema, de hecho, creo que está haciendo exactamente lo que se supone (redibujándose en función de su último estado [es decir, como estaba en tu subtrama]). Creo que tu problema es más que el wxFrame no es refrescante.

La manera más fácil de solucionar eso sería hacer que cambie el tamaño de su evento "Borrar". Algo como:

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])) 

El tamaño del conjunto provocaría que el marco y todos los controles que contiene sean redibujados.

Dicho esto, creo que compartir tu figura entre las dos figuras es peligroso. Pude producir algunos errores graves al hacer clic/cambiar el tamaño de las cosas en diferentes combinaciones. En ocasiones, su figura sería recogida de basura cuando el bastidor auxiliar estaba cerrado, por lo que no está disponible para su bastidor principal.

+0

Cambiar el tamaño no sería fácil de usar en mi caso, pero gracias, parece que lo mejor que puedo hacer es evitar compartir la figura. – Alex

+0

'self.axe.clear()' ¡es muy lento! Mi aplicación, necesito trazar durante mucho tiempo, 'self.axe.clear()' colgará mi aplicación por 0.5s :( –