(Python) 我的滑块无法在 FigureCanvasTkAgg 中工作

(Python) My slider cannot work in FigureCanvasTkAgg

我尝试在以下环境中设计一个简单的滑块;但是,它无法工作

注意:我使用的是Jupyter Notebook,所以我使用了FigureCanvasTkAgg和TkAgg。

注:我参考了下面的精彩讨论;但是,还是不行。

from tkinter import *
import tkinter.ttk as ttk
import matplotlib
import matplotlib.pyplot as plt
%matplotlib widget
from matplotlib.widgets import Slider
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
matplotlib.use('TkAgg')

root = Tk()
root.title('TEST')
root.geometry("800x800")

def plot_noise():
    fig = plt.Figure()                       
    canvas = FigureCanvasTkAgg(fig, root)     
    canvas.get_tk_widget().grid(row=6, column=0, columnspan=3, rowspan=3, sticky=W+E+N+S, padx=0, pady=0)  
    slider_bar = fig.add_axes([0.12, 0.1, 0.78, 0.03])
    slider_de = matplotlib.widgets.Slider(slider_bar, 's_bar', 0, 124, valinit=20)

ttk.Label(root,text = "Push the Button", font=('Arial', 25)).grid(column=0, row=0, ipadx=5, pady=5, sticky=W+N)  
resultButton = ttk.Button(root, text = 'show', command = plot_noise)
resultButton.grid(column=0, row=1, pady=15, sticky=W)

root.mainloop()

但是,滑块无法工作。我的意思是我不能移动滑块(没有错误弹出。)

如何解决?谢谢!

source code 我发现了你的问题:

""" The base class for constructing Slider widgets. Not intended for direct usage. For the slider to remain responsive you must maintain a reference to it. """

问题是您的 Slider 被垃圾回收了。您可以通过以下方式证明:

    global slider_de
    slider_bar = fig.add_axes([0.12, 0.1, 0.78, 0.03])
    slider_de = matplotlib.widgets.Slider(slider_bar, 's_bar', 0, 124, valinit=20)

另见 report of this bug and the given explaination in the docs:

The canvas retains only weak references to instance methods used as callbacks. Therefore, you need to retain a reference to instances owning such methods. Otherwise the instance will be garbage-collected and the callback will vanish.

这种架构的原因也可以在the source中找到:

In practice, one should always disconnect all callbacks when they are no longer needed to avoid dangling references (and thus memory leaks). However, real code in Matplotlib rarely does so, and due to its design, it is rather difficult to place this kind of code. To get around this, and prevent this class of memory leaks, we instead store weak references to bound methods only, so when the destination object needs to die, the CallbackRegistry won't keep it alive.