【问题标题】:matplotlib animation embedded in tkinter : update function never called嵌入 tkinter 的 matplotlib 动画:从未调用过更新函数
【发布时间】:2023-03-15 07:34:02
【问题描述】:

我一直在尝试将 matplotlib 动画嵌入 tkinter。 这个应用程序的目标是使用 rk4 方法模拟一些微分方程,并在模拟过程中显示实时图表。

事实上,情节正确地嵌入到了 tkinter 框架中。 但是,动画从未运行,我注意到更新函数从未被调用。

我一直在到处寻找,但没有找到任何东西。

感谢您的帮助。

这是一个 GUI 类的代码示例,显示了我在哪里执行动画

  # called when I click on a button "start simulation"
  def plot_neutrons_flow(self):

    # getting parameters from the graphical interface 
    if not self._started: 
      I0 = float(self._field_I0.get())
      X0 = float(self._field_X0.get())
      flow0 = float(self._field_flow0.get())
      time_interval = float(self._field_time_interval.get())
      stop = int(self._field_stop.get())

      FLOW_CI = [I0, X0, flow0] # [I(T_0), X(T_0), PHI[T_0]]

      self._simulation = NeutronsFlow(
        edo=neutrons_flow_edo, 
        t0=0,
        ci=FLOW_CI,
        time_interval=time_interval,
        stop=hour_to_seconds(stop)
      )

      # launch the animation
      self._neutrons_flow_plot.animate(self._simulation)
      self._started = True

这是 matplotlib 动画的代码:

import matplotlib
import tkinter as tk
import matplotlib.pyplot as plt
import matplotlib.animation as animation

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 
from matplotlib.figure import Figure
from matplotlib import style

matplotlib.use("TkAgg")
style.use('seaborn-whitegrid')

class PlotAnimation(FigureCanvasTkAgg):
  def __init__(self, tk_root):
    self._figure = Figure(dpi=100)
    # bind plot to tkinter frame
    super().__init__(self._figure, tk_root)

    x_label = "Temps (h)"
    y_label = "Flux / Abondance"

    self._axes = self._figure.add_subplot(111, xlabel=x_label, ylabel=y_label, yscale="log")
    self.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)


  def update(self, interval):
    # this is never called

    # get data from rk4 simulation
    time_set = self._simulation.get_time_set()
    y_set = self._simulation.get_y_set()


    self._axes.clear()
    self._axes.plot(time_set, y_set, visible=True, linewidth=1)
    self._axes.legend(fancybox=True)

    # redraw canvas
    self.draw_idle()

  def animate(self, simulation):
    # this is called

    self._simulation = simulation
    # simulate differential equations with rk4 method
    self._simulation.resolve()

    # https://github.com/matplotlib/matplotlib/issues/1656
    anim = animation.FuncAnimation(
      self._figure, 
      self.update,
      interval=1000
    )

编辑:

解决方法是直接在init方法中实例化FuncAnimation函数

【问题讨论】:

    标签: matplotlib animation tkinter numerical-methods


    【解决方案1】:

    animation module 的文档中所示(强调我的)

    (...) 保持对实例对象的引用至关重要。这 动画由计时器推进(通常来自主机 GUI 框架),动画对象持有唯一的引用。如果 您没有对 Animation 对象的引用,它(因此 计时器),将被垃圾收集,这将停止动画。

    您需要从您的 animate() 函数中返回 anim 对象,并将其存储在您的代码中的某个位置,以便它不会被垃圾回收

    【讨论】:

    • 我应该将它存储在“PlotAnimation”类还是这个类之外?我已经在我的 GUI 类中尝试了“self._animation = self._neutrons_flow_plot.animate(self._simulation)”,我在其中实例化了 animate 函数,但它不起作用。
    • 不要认为这很重要,只要它保存在某个地方。我认为里面会在概念上有意义。
    • 谢谢,我已经做到了,但也没有用。
    • 您是否还在animate 函数的末尾添加了return anim?如果它仍然不起作用,那么我们需要一个 MVCE 来测试您的代码
    • 我通过在 init 函数中直接实例化 FuncAnimation 使其工作。要编辑我的帖子。
    猜你喜欢
    • 1970-01-01
    • 2014-02-07
    • 2019-04-08
    • 2017-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多