2010-03-14 184 views
11

我無法理解如何刷新FigureCanvasWxAgg實例。這裏是例子:matplotlib:如何刷新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()  

我感興趣的操作順序如下:

  • 運行腳本
  • 調整主框架
  • 按情節按鈕
  • 雙擊on plot
  • 按清除按鈕

現在我在主框架圖上弄得一團糟。如果我調整框架大小,它會正確重畫。我的問題是我應該添加到我的代碼來做到這一點,而無需調整大小?

通過一個 「爛攤子」 我的意思是這樣的:

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

在此先感謝。

+0

@Alex,我不確定你在問什麼,你是什麼意思的「混亂」?我試過你的代碼,我沒有看到任何問題。主框架調整大小ok,按鈕繪製繪圖,雙擊創建一個新的框架,顯示與main相同的圖形畫布,清除按鈕清除繪圖並關閉子框架。 – Mark 2010-03-15 16:02:17

+0

嗯..這很奇怪,我添加了清晰後的狀態圖片。 – Alex 2010-03-16 15:06:02

+0

我最初嘗試在Linux上,在Windows下我可以重現你的照片。這是因爲你在兩個wxFrames之間共享你的數字對象(可能不是一個好主意)。如果沒有人讓我猜,我今天晚上仔細看看。 – Mark 2010-03-16 20:44:53

回答

11

正如我在評論中所說的,我認爲圖形畫布刷新不是你的問題,事實上我認爲它正在做它應該做的事情(根據它的最後狀態重新繪製自己[就像它在你的subplot])。我認爲你的問題更多的是wxFrame不刷新。

解決這個問題的最簡單方法就是讓它在「清除」事件中自行調整大小。例如:

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

設置的大小將導致幀和它包含的所有控件被重繪。

這就是說,我認爲在兩個圖形之間分享你的身影是很危險的。通過點擊/調整不同組合的東西,我能夠產生一些嚴重的錯誤。有時你的身材會在子框架關閉時被垃圾收集,使其無法在主框架中使用。

+0

在我的情況下,調整大小不會對用戶友好,但是,謝謝,似乎我能做的最好的事情是避免共享該數字。 – Alex 2010-03-18 08:53:47

+0

'self.axe.clear()'非常慢!我的應用程序,我需要繪製很多時間,'self.axe.clear()'會將我的應用程序掛起0.5秒:( – 2012-12-26 10:28:36