【问题标题】:matplotlib: how to refresh figure.canvasmatplotlib:如何刷新 figure.canvas
【发布时间】:2011-01-27 08:48:48
【问题描述】:

我不明白如何刷新 FigureCanvasWxAgg 实例。示例如下:


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

我对以下操作序列感兴趣:

  • 运行脚本
  • 调整主框架的大小
  • 按下绘图按钮
  • 双击绘图
  • 按清除按钮

现在我在主框架图上弄得一团糟。如果我调整框架的大小,它会正确重绘。我的问题是我应该在代码中添加什么而不调整大小?

我所说的“混乱”是指这样的:

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

提前致谢。

【问题讨论】:

  • @Alex,我不确定你在问什么,你所说的“一团糟”是什么意思?我试过你的代码,我没有发现任何问题。主框架调整大小确定,按钮绘制绘图,双击创建一个显示与主框架相同的图形画布的新框架,清除按钮清除绘图并关闭子框架。
  • 嗯..好奇怪,我在Clear之后添加了状态的图片。
  • 我原来在Linux下试过,在Windows下可以重现你的图片。这是因为您在两个 wxFrames 之间共享您的图形对象(可能不是一个好主意)。如果没有人赌我,我今晚会仔细看看。
  • @Mark,谢谢,分享这个图是我提高性能的想法,因为我不想创建一个新图并再次绘制它。

标签: python wxpython matplotlib


【解决方案1】:

正如我在 cmets 中所说,我不认为图形画布刷新是你的问题,事实上我认为它正在做它应该做的事情(根据它的最后状态重新绘制自己 [即,就像它在你的子情节])。我认为您的问题更多是 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]))

设置的大小会导致框架及其包含的所有控件被重绘。

也就是说,我认为在两个 figurecanvas 之间共享您的身材是危险的。通过单击/调整不同组合的大小,我能够产生一些严重的错误。有时,当子框架关闭时,您的图形会被垃圾收集,使其无法用于您的主框架。

【讨论】:

  • 在我的情况下调整大小对用户来说并不友好,但是谢谢,我能做的最好的事情就是避免分享这个数字。
  • self.axe.clear() 很慢!我的应用程序,我需要绘制很多次,self.axe.clear() 将挂起我的应用程序 0.5s :(
猜你喜欢
  • 2017-01-06
  • 2016-12-25
  • 2012-07-01
  • 1970-01-01
  • 2018-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多