1

I try to design a simple slider in the following environment; however, it cannot work

Note: I use Jupyter Notebook, so I utilized FigureCanvasTkAgg and TkAgg.

Note: I referred to the following great discussion; however, it still cannot work.
Python: Embed a matplotlib plot with slider in tkinter properly

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()

However, the slider cannot work. I mean I cannot move the slider (no error pops out.)

How to fix that? Thanks!

enter image description here

Denny
  • 223
  • 2
  • 15
  • *it cannot work* is a real broad discription of your issue. What does not work and how you did plan to make this happen? As I see it the code does exactly what it should do. What are you missing here? – Thingamabobs Dec 28 '21 at 10:28
  • Does this answer your question? [Python: Embed a matplotlib plot with slider in tkinter properly](https://stackoverflow.com/questions/40325321/python-embed-a-matplotlib-plot-with-slider-in-tkinter-properly) – Thingamabobs Dec 28 '21 at 10:31
  • @Thingamabobs 1. The slider cannot move, which is my problem here. 2. My code just referred to the link you provided. The only difference is I just preserve the codes of slider. – Denny Dec 28 '21 at 10:33
  • and where is your `update` function then ? There are no instruction for `Slider.on_changed(function)`, so there will be no change made. – Thingamabobs Dec 28 '21 at 10:35
  • @Thingamabobs That function is not necessary actually. I just double checked that. If you delete that function, the slider can still work. – Denny Dec 28 '21 at 11:18
  • My bad and I'm sorry. I have provided an answer for you. – Thingamabobs Dec 28 '21 at 11:32

1 Answers1

1

In the source code I have found your issue:

""" 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. """

The problem is that your Slider get garbage collected. You can prove that by:

    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)

Also see the 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.

and the reason for this architecture is also found in 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.

Thingamabobs
  • 7,274
  • 5
  • 21
  • 54