【问题标题】:Embedding a matplotlib animation into a tkinter frame将 matplotlib 动画嵌入到 tkinter 帧中
【发布时间】:2014-02-07 11:33:41
【问题描述】:

对于一个项目,我正在开发一个简单的谐波运动模拟器(质量如何随时间振荡)。我已经正确生成了数据,并且已经在 tkinter 框架中生成了一个图表。目前它只显示一个静态图表,我的目标是随着时间的推移将图表显示为动画。

因此,为了方便起见,我使用以下代码创建了一个程序模型:

#---------Imports
from numpy import arange, sin, pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import tkinter as Tk
from tkinter import ttk
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
#---------End of imports

fig, ax = plt.subplots()

x = np.arange(0, 2*np.pi, 0.01)        # x-array
line, = ax.plot(x, np.sin(x))

def animate(i):
    line.set_ydata(np.sin(x+i/10.0))  # update the data
    return line,

ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), interval=25, blit=False)
#plt.show() #What I want the object in tkinter to appear as

root = Tk.Tk()

label = ttk.Label(root,text="SHM Simulation").grid(column=0, row=0)

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.show()
canvas.get_tk_widget().grid(column=0,row=1)

Tk.mainloop()

plt.show() 未注释时,此代码将在 tkinter 框架中显示我想要的动画。我希望能够将该动画放置在 tkinter 的框架内。

我也上过 matplotlib 网站,查看了所有动画示例,但没有一个有帮助。我还查看了 Embedding an animated matplotlib in tk 并将 tkinter 按钮放置在 pyplot 图形中,而我想将图形放置在 tkinter 框架中。

所以澄清一下,我希望能够将plt.show() 未注释时产生的动画放在 tkinter 帧中,即root = tk()

【问题讨论】:

    标签: python animation matplotlib tkinter python-embedding


    【解决方案1】:

    我修改了你的代码:

    #---------Imports
    from numpy import arange, sin, pi
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
    from matplotlib.figure import Figure
    import tkinter as Tk
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    #---------End of imports
    
    fig = plt.Figure()
    
    x = np.arange(0, 2*np.pi, 0.01)        # x-array
    
    def animate(i):
        line.set_ydata(np.sin(x+i/10.0))  # update the data
        return line,
    
    root = Tk.Tk()
    
    label = Tk.Label(root,text="SHM Simulation").grid(column=0, row=0)
    
    canvas = FigureCanvasTkAgg(fig, master=root)
    canvas.get_tk_widget().grid(column=0,row=1)
    
    ax = fig.add_subplot(111)
    line, = ax.plot(x, np.sin(x))
    ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), interval=25, blit=False)
    
    Tk.mainloop()
    

    【讨论】:

    • 突出显示关键修改和推理可以使这个答案更加有用。
    【解决方案2】:

    基于 user151522 在第一次尝试时对我不起作用的答案,我做了一些修改以在 python 3.7 中工作:

    #---------Imports
    
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
    
    import tkinter as tk
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    #---------End of imports
    
    
    
    from tkinter import Frame,Label,Entry,Button
    
    
    class Window(Frame):
    
        def __init__(self, master = None):
            Frame.__init__(self, master)
            self.master = master
            self.init_window()
    
    
        def Clear(self):      
            print("clear")
            self.textAmplitude.insert(0, "1.0")
            self.textSpeed.insert(0, "1.0")       
    
    
        def Plot(self):
            self.v = float(self.textSpeed.get())
            self.A = float(self.textAmplitude.get())
    
    
        def animate(self,i):
            self.line.set_ydata(self.A*np.sin(self.x+self.v*i))  # update the data
            return self.line,
    
    
        def init_window(self):
    
    
    
            self.master.title("Use Of FuncAnimation in tkinter based GUI")
            self.pack(fill='both', expand=1)     
    
            #Create the controls, note use of grid
    
            self.labelSpeed = Label(self,text="Speed (km/Hr)",width=12)
            self.labelSpeed.grid(row=0,column=1)
            self.labelAmplitude = Label(self,text="Amplitude",width=12)
            self.labelAmplitude.grid(row=0,column=2)
    
            self.textSpeed = Entry(self,width=12)
            self.textSpeed.grid(row=1,column=1)
            self.textAmplitude = Entry(self,width=12)
            self.textAmplitude.grid(row=1,column=2)
    
            self.textAmplitude.insert(0, "1.0")
            self.textSpeed.insert(0, "1.0")
            self.v = 1.0
            self.A = 1.0
    
    
            self.buttonPlot = Button(self,text="Plot",command=self.Plot,width=12)        
            self.buttonPlot.grid(row=2,column=1)
    
            self.buttonClear = Button(self,text="Clear",command=self.Clear,width=12)
            self.buttonClear.grid(row=2,column=2)
    
    
            self.buttonClear.bind(lambda e:self.Clear)
    
    
    
            tk.Label(self,text="SHM Simulation").grid(column=0, row=3)
    
            self.fig = plt.Figure()
    
            self.x = 20*np.arange(0, 2*np.pi, 0.01)        # x-array
    
    
            self.ax = self.fig.add_subplot(111)
            self.line, = self.ax.plot(self.x, np.sin(self.x))        
    
    
            self.canvas = FigureCanvasTkAgg(self.fig, master=self)
            self.canvas.get_tk_widget().grid(column=0,row=4)
    
    
            self.ani = animation.FuncAnimation(self.fig, self.animate, np.arange(1, 200), interval=25, blit=False)
    
    
    
    
    root = tk.Tk()
    root.geometry("700x400")
    app = Window(root)
    tk.mainloop()
    

    【讨论】:

      【解决方案3】:

      这个答案有望被允许。这是我最初发现这个问题时真正感兴趣的答案,即“将 Matplotlib 动画嵌入基于 tkinter 的 GUI”。

      上一个截图的代码已经被扩展,在这段代码中,画布被放置在一个类定义中,连同一些用于两个命令按钮的代码,这些按钮实际上并没有做“任何事情”,但结构是有可能进一步发展。

      以下截图是借助扩展代码生成的

      A screenshot of the SHM animation running from within a tkinter based GUI

      上面截图使用的扩展代码如下。

      
      from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
      
      import tkinter as tk
      from tkinter import Frame,Label,Entry,Button
      import numpy as np
      import matplotlib.pyplot as plt
      import matplotlib.animation as animation
      
      class Window(Frame):
      
          def __init__(self, master = None):
              Frame.__init__(self, master)
              self.master = master
              self.init_window()
      
      
          def Clear(self):
              x=0
      
      #    def Plot(self):
      #        x=0
      
          def init_window(self):
      
      
              def animate(i):
                 self.line.set_ydata(np.sin(self.x+i/10.0))  # update the data
                 return self.line,
      
              self.master.title("Use Of FuncAnimation in tkinter based GUI")
              self.pack(fill='both', expand=1)     
      
      #Create the controls, note use of grid
      
              self.labelSpeed = Label(self,text="Speed (km/Hr)",width=12)
              self.labelSpeed.grid(row=0,column=1)
              self.labelAmplitude = Label(self,text="Amplitude",width=12)
              self.labelAmplitude.grid(row=0,column=2)
      
              self.textSpeed = Entry(self,width=12)
              self.textSpeed.grid(row=1,column=1)
              self.textAmplitude = Entry(self,width=12)
              self.textAmplitude.grid(row=1,column=2)
      
      
      #        self.buttonPlot = Button(self,text="Plot",command=self.Plot,width=12)
              self.buttonPlot = Button(self,text="Plot",width=12)
              self.buttonPlot.grid(row=2,column=1)
              self.buttonClear = Button(self,text="Clear",command=self.Clear,width=12)
              self.buttonClear.grid(row=2,column=2)
      
      #        self.buttonClear.bind(lambda e:self.Plot)
              self.buttonClear.bind(lambda e:self.Clear)
      
      
      
              tk.Label(self,text="SHM Simulation").grid(column=0, row=3)
      
              self.fig = plt.Figure()
      
              self.x = np.arange(0, 2*np.pi, 0.01)        # x-array
      
      
              self.ax = self.fig.add_subplot(111)
              self.line, = self.ax.plot(self.x, np.sin(self.x))        
      
      
              self.canvas = FigureCanvasTkAgg(self.fig, master=self)
              self.canvas.get_tk_widget().grid(column=0,row=4)
      
      
              self.ani = animation.FuncAnimation(self.fig, animate, np.arange(1, 200), interval=25, blit=False)
      
      
      
      
      root = tk.Tk()
      root.geometry("700x400")
      app = Window(root)
      tk.mainloop()
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-03
        • 1970-01-01
        • 2017-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多