【问题标题】:Pause/Stop animation of matplotlib on button press embedded in tkintertkinter 中嵌入的按钮按下时 matplotlib 的暂停/停止动画
【发布时间】:2021-12-29 16:24:04
【问题描述】:

我正在使用来自 Tutorials Point 的以下代码。这里的 Quit 按钮会停止程序,但我想在按下另一个按钮时暂停动画。我在图中找到了对 onclick() 起作用的其他资源,但我想通过 Pause 按钮执行此操作。

我该如何实现?

import tkinter
from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler
from matplotlib import pyplot as plt, animation
import numpy as np

plt.rcParams["figure.figsize"] = [7.00, 3.50]
plt.rcParams["figure.autolayout"] = True

root = tkinter.Tk()
root.wm_title("Embedding in Tk")

plt.axes(xlim=(0, 2), ylim=(-2, 2))
fig = plt.Figure(dpi=100)
ax = fig.add_subplot(xlim=(0, 2), ylim=(-1, 1))
line, = ax.plot([], [], lw=2)

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()

toolbar = NavigationToolbar2Tk(canvas, root, pack_toolbar=False)
toolbar.update()

canvas.mpl_connect(
    "key_press_event", lambda event: print(f"you pressed {event.key}"))
canvas.mpl_connect("key_press_event", key_press_handler)

button = tkinter.Button(master=root, text="Quit", command=root.quit)
button.pack(side=tkinter.BOTTOM)

toolbar.pack(side=tkinter.BOTTOM, fill=tkinter.X)
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)

def init():
    line.set_data([], [])
    return line,

def animate(i):
    x = np.linspace(0, 2, 1000)
    y = np.sin(2 * np.pi * (x - 0.01 * i))
    line.set_data(x, y)
    return line,

anim = animation.FuncAnimation(fig, animate, init_func=init,frames=200, interval=20, blit=True)

tkinter.mainloop()

【问题讨论】:

    标签: python matplotlib tkinter


    【解决方案1】:

    我的答案基于答案here,它很好地解释了使用单击暂停动画(您已经研究过)。我的答案的功能与示例相同,只是将暂停功能修改为由 tkinter 按钮而不是鼠标单击驱动并在代码中实现。

    import matplotlib.pyplot as plt
    import numpy as np
    import matplotlib.animation as animation
    import tkinter as tkinter
    from matplotlib.backends.backend_tkagg import (
        FigureCanvasTkAgg, NavigationToolbar2Tk)
    from matplotlib.backend_bases import key_press_handler
    
    plt.rcParams["figure.figsize"] = [7.00, 3.50]
    plt.rcParams["figure.autolayout"] = True
    
    root = tkinter.Tk()
    root.wm_title("Embedding in Tk")
    
    plt.axes(xlim=(0, 2), ylim=(-1, 1))
    fig = plt.Figure(dpi=100)
    ax = fig.add_subplot(xlim=(0, 2), ylim=(-1, 1))
    line, = ax.plot([], [], lw=2)
    
    canvas = FigureCanvasTkAgg(fig, master=root)
    canvas.draw()
    
    toolbar = NavigationToolbar2Tk(canvas, root, pack_toolbar=False)
    toolbar.update()
    
    canvas.mpl_connect(
        "key_press_event", lambda event: print(f"you pressed {event.key}"))
    canvas.mpl_connect("key_press_event", key_press_handler)
    
    button = tkinter.Button(master=root, text="Quit", command=root.quit)
    button.pack(side=tkinter.BOTTOM)
    
    # Pause button and function
    pause = False
    def pause_animation():
        global pause
        pause ^= True
    button2 = tkinter.Button(master=root, text="Pause", command=pause_animation)
    button2.pack(side=tkinter.BOTTOM)
    
    toolbar.pack(side=tkinter.BOTTOM, fill=tkinter.X)
    canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
    
    def animation_data():
        tMax = 100  # 0.01*tMax/dt needs to be an int for smooth animation
        dt = 1      # Changing dt changes the "speed" that the curve moves on the plot
        y = 0.0
        t = 0
        x = np.linspace(0, 2, 1000)
        while t<tMax:   # This is included to reset t so it doesn't get too large for long runs
            if not pause:
                y = np.sin(2 * np.pi * (x - 0.01 *t))
                t = t + dt
            yield x, y
    
    def animate(animation_data):
        x, y = animation_data[0], animation_data[1]
        line.set_data(x, y)
        return line,
    
    ani = animation.FuncAnimation(fig, animate, animation_data, blit=True, interval=10,
        repeat=True)
    
    tkinter.mainloop()
    

    【讨论】:

    • 是的,我已经看到了这个答案。但是该代码的问题在于,它在图形暂停时在后台生成点,而在恢复时,它会从一个全新的位置而不是暂停的位置显示绘图。
    • @solo 很抱歉,但我认为您没有运行此程序。当您按下暂停时,它会停止重新计算点,并继续将相同的固定点提供给绘图,这实际上会冻结图像。它仅在pause=False 时开始重新计算点,这意味着它从绘图暂停的位置开始
    • 尝试在x, y = animation_data[0], animation_data[1] 之后的行中使用print(y[0] 运行它。您会看到,当您按下暂停时,该值不会改变,即使它不断打印出一个“新”值
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-19
    • 2019-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多