From 95cf15471462f7e9dbfe97bf5f37c5c343975f64 Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Thu, 7 Aug 2025 03:10:19 +0300 Subject: [PATCH 1/3] widgets.pyi: Fix SliderBase's valfmt type --- lib/matplotlib/widgets.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/widgets.pyi b/lib/matplotlib/widgets.pyi index 0fcd1990e17e..7ef546dc5fae 100644 --- a/lib/matplotlib/widgets.pyi +++ b/lib/matplotlib/widgets.pyi @@ -64,7 +64,7 @@ class SliderBase(AxesWidget): valmax: float valstep: float | ArrayLike | None drag_active: bool - valfmt: str + valfmt: str | None def __init__( self, ax: Axes, @@ -73,7 +73,7 @@ class SliderBase(AxesWidget): closedmax: bool, valmin: float, valmax: float, - valfmt: str, + valfmt: str | None, dragging: Slider | None, valstep: float | ArrayLike | None, ) -> None: ... From 4cdc0469200b5080ff32042f67bf8e948211ac12 Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Sun, 27 Jul 2025 12:52:29 +0300 Subject: [PATCH 2/3] {,Range}Slider: accept callable valfmt arguments Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- lib/matplotlib/widgets.py | 23 ++++++++++++++++------- lib/matplotlib/widgets.pyi | 6 +++--- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 9c676574310c..dbd85c109290 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -364,8 +364,9 @@ def __init__(self, ax, label, valmin, valmax, *, valinit=0.5, valfmt=None, The slider initial position. valfmt : str, default: None - %-format string used to format the slider value. If None, a - `.ScalarFormatter` is used instead. + The way to format the slider value. If a string, it must be in %-format. + If a callable, it must have the signature ``valfmt(val: float) -> str``. + If None, a `.ScalarFormatter` is used. closedmin : bool, default: True Whether the slider interval is closed on the bottom. @@ -547,7 +548,10 @@ def _update(self, event): def _format(self, val): """Pretty-print *val*.""" if self.valfmt is not None: - return self.valfmt % val + if callable(self.valfmt): + return self.valfmt(val) + else: + return self.valfmt % val else: _, s, _ = self._fmt.format_ticks([self.valmin, val, self.valmax]) # fmt.get_offset is actually the multiplicative factor, if any. @@ -644,9 +648,11 @@ def __init__( The initial positions of the slider. If None the initial positions will be at the 25th and 75th percentiles of the range. - valfmt : str, default: None - %-format string used to format the slider values. If None, a - `.ScalarFormatter` is used instead. + valfmt : str or callable, default: None + The way to format the range's minimal and maximal values. If a + string, it must be in %-format. If a callable, it must have the + signature ``valfmt(val: float) -> str``. If None, a + `.ScalarFormatter` is used. closedmin : bool, default: True Whether the slider interval is closed on the bottom. @@ -890,7 +896,10 @@ def _update(self, event): def _format(self, val): """Pretty-print *val*.""" if self.valfmt is not None: - return f"({self.valfmt % val[0]}, {self.valfmt % val[1]})" + if callable(self.valfmt): + return f"({self.valfmt(val[0])}, {self.valfmt(val[1])})" + else: + return f"({self.valfmt % val[0]}, {self.valfmt % val[1]})" else: _, s1, s2, _ = self._fmt.format_ticks( [self.valmin, *val, self.valmax] diff --git a/lib/matplotlib/widgets.pyi b/lib/matplotlib/widgets.pyi index 7ef546dc5fae..cc7d715e017e 100644 --- a/lib/matplotlib/widgets.pyi +++ b/lib/matplotlib/widgets.pyi @@ -64,7 +64,7 @@ class SliderBase(AxesWidget): valmax: float valstep: float | ArrayLike | None drag_active: bool - valfmt: str | None + valfmt: str | Callable[[float], str] | None def __init__( self, ax: Axes, @@ -73,7 +73,7 @@ class SliderBase(AxesWidget): closedmax: bool, valmin: float, valmax: float, - valfmt: str | None, + valfmt: str | Callable[[float], str] | None, dragging: Slider | None, valstep: float | ArrayLike | None, ) -> None: ... @@ -130,7 +130,7 @@ class RangeSlider(SliderBase): valmax: float, *, valinit: tuple[float, float] | None = ..., - valfmt: str | None = ..., + valfmt: str | Callable[[float], str] | None = ..., closedmin: bool = ..., closedmax: bool = ..., dragging: bool = ..., From b6d74413c81a2d2cb58f5db7e51f095912f63b20 Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Tue, 5 Aug 2025 10:33:03 +0300 Subject: [PATCH 3/3] {,Range}Slider: Add release notes for valfmt arguments Co-authored-by: Elliott Sales de Andrade --- doc/users/next_whats_new/sliders_callable_valfmt.rst | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 doc/users/next_whats_new/sliders_callable_valfmt.rst diff --git a/doc/users/next_whats_new/sliders_callable_valfmt.rst b/doc/users/next_whats_new/sliders_callable_valfmt.rst new file mode 100644 index 000000000000..1d350dba348a --- /dev/null +++ b/doc/users/next_whats_new/sliders_callable_valfmt.rst @@ -0,0 +1,6 @@ +Callable *valfmt* for ``Slider`` and ``RangeSlider`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In addition to the existing %-format string, the *valfmt* parameter of +`~.matplotlib.widgets.Slider` and `~.matplotlib.widgets.RangeSlider` now +also accepts a callable of the form ``valfmt(val: float) -> str``.