【问题标题】:FuncAnimation only starts after window resizeFuncAnimation 仅在窗口调整大小后启动
【发布时间】:2019-09-22 19:48:21
【问题描述】:

我正在制作一个应该可视化传感器数据的应用程序。因此,我使用带有 tkinter 的 python 作为 gui 框架和 matplotlib 来可视化数据。该图应显示当前传感器值,因此应为动画。 但是,由于我不想在未连接传感器时为图形设置动画,因此我添加了一个connect 按钮,该按钮需要启动动画。 这一切都按预期工作,但是,动画仅在我调整 tkinter 窗口大小后才开始。 我假设这会触发所有组件的重绘,但我不知道如何从代码中触发。

我已经尝试调用函数 root.update()root.update_idletasks() 但这没有帮助。

这是代码的最小示例:

import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.animation as animation
import matplotlib.pyplot as plt

from matplotlib import style


root = tk.Tk()
style.use('fivethirtyeight')

ys = [i for i in range(100)]

def animate(i, ax1, line):
    global ys
    ys = ys[1:] + [ys[0]]
    line.set_ydata(ys)

    # Draw x and y lists
    ax1.relim()
    ax1.autoscale_view(True,True,True)

    return line

class Gui():
    def __init__(self):
        global ys
        self._fig = plt.figure()
        self._ax1 = self._fig.add_subplot(1,1,1)

        self._line, = self._ax1.plot(ys)
        plt.xticks(ha='right')
        plt.subplots_adjust(bottom=0.30)
        plt.title('Air pressure measured')
        plt.ylabel('Sensor value')

        top_frame = tk.Frame(root, bg='cyan', width = 450, height=50)
        top_frame.pack(side=tk.LEFT, anchor=tk.N, pady=10)
        self.connectButton = tk.Button(top_frame, 
                                        text="connect",
                                        command=self.toggleAnimate)
        self.connectButton.pack()

        self._canvas = FigureCanvasTkAgg(self._fig, master=root)
        self._canvas.draw()
        self._canvas.get_tk_widget().pack()

    def start(self):
        root.mainloop()

    def toggleAnimate(self):
        self._animate = animation.FuncAnimation(self._fig, animate, fargs=(self._ax1, self._line), interval=100, blit=False)
        root.update_idletasks()
        root.update()

if __name__ == "__main__":
    g = Gui()
    g.start()

【问题讨论】:

    标签: python matplotlib tkinter


    【解决方案1】:

    您需要在FigureCanvasTkAgg 上拨打一次draw_idle 才能让事情顺利进行。

    我将root 放置在GUI 中,并删除了对updateupdate_idletasks 的不必要调用,这些调用可能会干扰mainloop
    我还将您的 canvas 打包到了 frame 中,但如果您愿意,可以将其重新定位到 root

    import tkinter as tk
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
    import matplotlib.animation as animation
    import matplotlib.pyplot as plt
    
    from matplotlib import style
    
    
    style.use('fivethirtyeight')
    
    ys = [i for i in range(100)]
    
    def animate(i, ax1, line):
        global ys
        ys = ys[1:] + [ys[0]]
        line.set_ydata(ys)
    
        # Draw x and y lists
        ax1.relim()
        ax1.autoscale_view(True,True,True)
    
        return line
    
    class Gui():
        def __init__(self):
            self.root = tk.Tk()
            self._fig = plt.figure()
            self._ax1 = self._fig.add_subplot(1,1,1)
    
            self._line, = self._ax1.plot(ys)
            plt.xticks(ha='right')
            plt.subplots_adjust(bottom=0.30)
            plt.title('Air pressure measured')
            plt.ylabel('Sensor value')
    
            top_frame = tk.Frame(self.root, bg='cyan', width = 450, height=50)
            top_frame.pack(side=tk.LEFT, anchor=tk.N, pady=10)
            self.connectButton = tk.Button(top_frame, 
                                            text="connect",
                                            command=self.toggleAnimate)
            self.connectButton.pack()
    
            self._canvas = FigureCanvasTkAgg(self._fig, master=top_frame) #master=self.root)
            self._canvas.get_tk_widget().pack(expand=True, side=tk.LEFT, anchor=tk.N, pady=10, padx=10)
            self._canvas.draw()        
            self._animate = None
    
        def start(self):
            self.root.mainloop()
    
        def toggleAnimate(self):
            if self._animate is None:
                self._canvas.draw_idle()
                self._animate = animation.FuncAnimation(self._fig, animate, fargs=(self._ax1, self._line), interval=100) #, blit=False)
    
    
    if __name__ == "__main__":
        g = Gui()
        g.start()
    

    【讨论】:

      猜你喜欢
      • 2015-03-27
      • 1970-01-01
      • 2021-01-08
      • 1970-01-01
      • 2013-09-19
      • 2018-11-01
      • 2019-10-12
      • 1970-01-01
      相关资源
      最近更新 更多