Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 413e851

Browse files
committed
allow slider to snap to an array of values
1 parent f70557f commit 413e851

File tree

3 files changed

+40
-4
lines changed

3 files changed

+40
-4
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Sliders can now snap to arbitrary values
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
The `~matplotlib.widgets.Slider` UI widget now accepts the optional
5+
argument *valsnap*. This generalizes the discrete value snapping introduced
6+
by the *valstep* argument, allowing the user to pass an array of values,
7+
to snap to.

lib/matplotlib/tests/test_widgets.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,17 @@ def test_slider_valmin_valmax():
267267
assert slider.val == slider.valmax
268268

269269

270+
def test_slider_valstep_valsnap():
271+
fig, ax = plt.subplots()
272+
slider = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
273+
valinit=11.4, valstep=1)
274+
assert slider.val == 11
275+
276+
slider = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
277+
valinit=11.4, valsnap=[0, 1, 5.5, 19.7])
278+
assert slider.val == 5.5
279+
280+
270281
def test_slider_horizontal_vertical():
271282
fig, ax = plt.subplots()
272283
slider = widgets.Slider(ax=ax, label='', valmin=0, valmax=24,

lib/matplotlib/widgets.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ class Slider(AxesWidget):
255255
def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None,
256256
closedmin=True, closedmax=True, slidermin=None,
257257
slidermax=None, dragging=True, valstep=None,
258-
orientation='horizontal', **kwargs):
258+
orientation='horizontal', valsnap=None, **kwargs):
259259
"""
260260
Parameters
261261
----------
@@ -297,10 +297,15 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None,
297297
298298
valstep : float, default: None
299299
If given, the slider will snap to multiples of *valstep*.
300+
If both *valsnap* and *valstep* are set an error is raised.
300301
301302
orientation : {'horizontal', 'vertical'}, default: 'horizontal'
302303
The orientation of the slider.
303304
305+
valsnap : 1D array-like, default: None
306+
If given, the slider will snap to nearest value in *valsnap*.
307+
If both *valsnap* and *valstep* are set an error is raised.
308+
304309
Notes
305310
-----
306311
Additional kwargs are passed on to ``self.poly`` which is the
@@ -319,6 +324,9 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None,
319324
if slidermax is not None and not hasattr(slidermax, 'val'):
320325
raise ValueError(
321326
f"Argument slidermax ({type(slidermax)}) has no 'val'")
327+
if valstep is not None and valsnap is not None:
328+
raise ValueError("kwargs 'valsnap' and 'valstep' cannot "
329+
"be used simultaneously. ")
322330
_api.check_in_list(['horizontal', 'vertical'], orientation=orientation)
323331

324332
self.orientation = orientation
@@ -330,6 +338,15 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None,
330338
self.valmin = valmin
331339
self.valmax = valmax
332340
self.valstep = valstep
341+
self.valsnap = valsnap
342+
if self.valsnap is not None:
343+
self.valsnap = np.sort(self.valsnap)
344+
elif self.valstep is not None:
345+
self.valsnap = np.arange(
346+
self.valmin,
347+
self.valmax + self.valstep,
348+
self.valstep
349+
)
333350
valinit = self._value_in_bounds(valinit)
334351
if valinit is None:
335352
valinit = valmin
@@ -401,9 +418,10 @@ def observers(self):
401418

402419
def _value_in_bounds(self, val):
403420
"""Makes sure *val* is with given bounds."""
404-
if self.valstep:
405-
val = (self.valmin
406-
+ round((val - self.valmin) / self.valstep) * self.valstep)
421+
if self.valsnap is not None:
422+
idx = np.searchsorted(self.valsnap, val, side="left")
423+
candidates = self.valsnap[[idx-1, min(idx, self.valsnap.size-1)]]
424+
val = candidates[np.argmin(np.abs(candidates - val))]
407425

408426
if val <= self.valmin:
409427
if not self.closedmin:

0 commit comments

Comments
 (0)