【问题标题】:How to hide animated subplots in a canvas如何在画布中隐藏动画子图
【发布时间】:2015-09-03 09:14:07
【问题描述】:

我正在用 python 中的 tkinter 编写一个 gui 来显示一些图。这些图必须是动画的,因为数据集每隔几秒就会更新一次。 目前我在一帧中有 4 个地块。

我想要一个菜单​​或按钮或其他东西,可以隐藏其中一个图,并在行/列中展开另一个图。但即使隐藏一个子情节也行不通。这是我的代码:

class Window(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.frame = tk.Frame(self)
        self.frame.pack()

        self.menu = tk.Menu(self)
        self.config(menu=self.menu)

        self.filemenu = tk.Menu(self.menu)
        self.menu.add_cascade(label = 'View', menu = self.filemenu)
        self.filemenu.add_command(label = 'Turn on graph 1', command=self.dummy0)
        self.filemenu.add_command(label = 'Turn off graph 1', command=self.dummy1)

        fpath = '../files/somefile.txt'

        self.fig = Figure(figsize = (12, 8), tight_layout = True)
        gs = gridspec.GridSpec(2, 2)
        self.ax0 = self.fig.add_subplot(gs[0, 0])
        self.ax1 = self.fig.add_subplot(gs[0, 1])
        self.ax2 = self.fig.add_subplot(gs[1, 0])
        self.ax3 = self.fig.add_subplot(gs[1, 1])

        self.canvas = FigureCanvasTkAgg(self.fig, self.frame)
        ani0 = animation.FuncAnimation(self.fig, self.animate, interval = 1000, fargs = (self.ax0, fpath, 'TankDruck O2', 60))
        ani1 = animation.FuncAnimation(self.fig, self.animate, interval = 1000, fargs = (self.ax1, fpath, 'TankDruck N2', 60))
        ani2 = animation.FuncAnimation(self.fig, self.animate, interval = 1000, fargs = (self.ax2, fpath, 'TankStand O2', 60))
        ani3 = animation.FuncAnimation(self.fig, self.animate, interval = 1000, fargs = (self.ax3, fpath, 'TankStand N2', 60))
        self.canvas.show()
        #self.canvas.get_tk_widget().grid(row = 0, column = 0)
        self.canvas.get_tk_widget().pack(side=tk.LEFT, fill = tk.BOTH, expand = True)

    def dummy0(self):
        self.ax0.set_visible(True)

    def dummy1(self):
        self.ax0.set_visible(False)
        self.canvas.draw()

    def animate(self, i, ax, path, var, tstep):
        reader = Reader(path)
        reader.read(var, tstep)
        xdata, ydata, var, unit = reader.get_data()
        ax.clear()
        ax.set_ylabel(var + ' in ' + unit)
        ax.set_xlabel('Seconds since 01.01.2000')
        ax.plot(xdata, ydata)

当我执行这个时,它工作得很好。就在我想隐藏子图时,程序抛出错误,但继续运行:

Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib64/python2.7/lib-tk/Tkinter.py", line 1470, in __call__
  return self.func(*args)
File "/usr/lib64/python2.7/lib-tk/Tkinter.py", line 531, in callit
  func(*args)
File "/usr/lib64/python2.7/site-packages/matplotlib/backends/backend_tkagg.py", line 363, in idle_draw
  self.draw()
File "/usr/lib64/python2.7/site-packages/matplotlib/backends/backend_tkagg.py", line 348, in draw
  FigureCanvasAgg.draw(self)
File "/usr/lib64/python2.7/site-packages/matplotlib/backends/backend_agg.py", line 451, in draw
  self.figure.draw(self.renderer)
File "/usr/lib64/python2.7/site-packages/matplotlib/artist.py", line 54, in draw_wrapper
  draw(artist, renderer, *args, **kwargs)
File "/usr/lib64/python2.7/site-packages/matplotlib/figure.py", line 966, in draw
  self.tight_layout(renderer, **self._tight_parameters)
File "/usr/lib64/python2.7/site-packages/matplotlib/figure.py", line 1605, in tight_layout
rect=rect)
File "/usr/lib64/python2.7/site-packages/matplotlib/tight_layout.py", line 352, in get_tight_layout_figure
  pad=pad, h_pad=h_pad, w_pad=w_pad)
File "/usr/lib64/python2.7/site-packages/matplotlib/tight_layout.py", line 131, in auto_adjust_subplotpars
  fig.transFigure.inverted())
File "/usr/lib64/python2.7/site-packages/matplotlib/transforms.py", line 1049, in __init__
  assert bbox.is_bbox
AttributeError: 'NoneType' object has no attribute 'is_bbox'

有谁知道我该如何处理这个问题?在最好的情况下,绘图 ax0 会消失,而 ax1 会扩大以填满整行。 还是我需要使用多个画布或类似的东西?

提前致谢!

【问题讨论】:

    标签: python canvas matplotlib tkinter subplot


    【解决方案1】:

    我自己找到了解决方案。问题是图形的tight_layout。我将调用改为:

    self.fig = Figure(figsize = (12, 8))
    

    现在它可以正常工作了。

    我也改了 dummy0 和 dummy1:

    def dummy0(self):
        self.ax0.set_visible(True)
        self.ax1.change_geometry(2,2,2) 
        self.canvas.draw()
    
    def dummy1(self):
        self.ax0.set_visible(False)
        self.ax1.change_geometry(2,1,1)
        self.canvas.draw()
    

    所以另一个情节将填满这一行。以防万一将来有人也需要它。

    再见。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-03
      • 2018-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-23
      • 1970-01-01
      相关资源
      最近更新 更多