0

I can't get the matplotlib slider to respond inside a PyQt6 application. Here is a sample program. I know there is no binding on the slider (that's not the problem). The problem is the slider itself doesn't respond to mouse events (ie. clicking, dragging).

I'm using python 3.10.12, matplotlib 3.8.2, PyQt6 6.6.1


import numpy as np

from matplotlib.backends.backend_qtagg import FigureCanvas
from matplotlib.backends.backend_qtagg import \
    NavigationToolbar2QT as NavigationToolbar
from matplotlib.backends.qt_compat import QtWidgets
from matplotlib.figure import Figure
from matplotlib.widgets import Slider

class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self._main = QtWidgets.QWidget()
        self.setCentralWidget(self._main)
        layout = QtWidgets.QVBoxLayout(self._main)

        fig = Figure(figsize=(5, 3))
        static_canvas = FigureCanvas(fig)
        layout.addWidget(NavigationToolbar(static_canvas, self))
        layout.addWidget(static_canvas)

        self._static_ax = static_canvas.figure.subplots()
        t = np.linspace(0, 10, 501)
        self._static_ax.plot(t, np.tan(t), ".")

        fig.subplots_adjust(left=0.25)

        axamp = fig.add_axes([0.1, 0.25, 0.0225, 0.63])
        amp_slider = Slider(
            ax=axamp,
            label="Amplitude",
            valmin=0,
            valmax=10,
            valinit=6,
            orientation="vertical"
        )

        amp_slider.on_changed(self.slider_callback)
    
    def slider_callback(self):
        print("slider is changing")

if __name__ == "__main__":
    # Check whether there is already a running QApplication (e.g., if running
    # from an IDE).
    qapp = QtWidgets.QApplication.instance()
    if not qapp:
        qapp = QtWidgets.QApplication(sys.argv)

    app = ApplicationWindow()
    app.show()
    app.activateWindow()
    app.raise_()
    qapp.exec()
4
  • That slider isn't attached to anything that will eventually tell it to do something else. The only argument that makes it persistent is the ax argument, which only tells where the slider would be put (as explained in the Slider docs) but won't do anything beyond avoiding destruction. The slider demo clearly shows that the update function has to be registered to the slider changes: amp_slider.on_changed(<function that actually updates the figure>). Commented Dec 15, 2023 at 5:15
  • I know there is no callback function registered. As I explained, that's not the problem. Even if I register a callback function on the sliders on_changed event it will never get called because the slider itself doesn't move and will never generate the on_changed event. Commented Dec 15, 2023 at 5:28
  • 1
    Keep the slider instance alive by storing it as a data attribute(member variable). Commented Dec 18, 2023 at 14:25
  • Thanks @relent95. I assumed that since the slider was added to the axes that there would be an internal reference and that wouldn't be necessary. Commented Dec 18, 2023 at 15:24

1 Answer 1

0

As per the comment by @relent95, I just needed to store a reference to the slider instance.

self.amp_slider = Slider(...)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.