Skip to content

Commit c3e65f1

Browse files
authored
Merge pull request #8134 from heath730/slider_updates
Update Slider docs and type check slidermin and slidermax.
2 parents ba418fd + 2b42285 commit c3e65f1

File tree

2 files changed

+100
-86
lines changed

2 files changed

+100
-86
lines changed

lib/matplotlib/tests/test_widgets.py

+38
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
from numpy.testing import assert_allclose
1515

16+
import pytest
17+
1618

1719
def get_ax():
1820
fig, ax = plt.subplots(1, 1)
@@ -275,3 +277,39 @@ def test_check_radio_buttons_image():
275277
widgets.RadioButtons(rax1, ('Radio 1', 'Radio 2', 'Radio 3'))
276278
widgets.CheckButtons(rax2, ('Check 1', 'Check 2', 'Check 3'),
277279
(False, True, True))
280+
281+
282+
def test_slider_slidermin_slidermax_invalid():
283+
fig, ax = plt.subplots()
284+
# test min/max with floats
285+
with pytest.raises(ValueError):
286+
widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
287+
slidermin=10.0)
288+
with pytest.raises(ValueError):
289+
widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
290+
slidermax=10.0)
291+
292+
293+
def test_slider_slidermin_slidermax():
294+
fig, ax = plt.subplots()
295+
slider_ = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
296+
valinit=5.0)
297+
298+
slider = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
299+
valinit=1.0, slidermin=slider_)
300+
assert slider.val == slider_.val
301+
302+
slider = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
303+
valinit=10.0, slidermax=slider_)
304+
assert slider.val == slider_.val
305+
306+
307+
def test_slider_valmin_valmax():
308+
fig, ax = plt.subplots()
309+
slider = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
310+
valinit=-10.0)
311+
assert slider.val == slider.valmin
312+
313+
slider = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
314+
valinit=25.0)
315+
assert slider.val == slider.valmax

lib/matplotlib/widgets.py

+62-86
Original file line numberDiff line numberDiff line change
@@ -266,100 +266,78 @@ class Slider(AxesWidget):
266266
"""
267267
A slider representing a floating point range.
268268
269-
For the slider to remain responsive you must maintain a
270-
reference to it.
271-
272-
The following attributes are defined
273-
*ax* : the slider :class:`matplotlib.axes.Axes` instance
274-
275-
*val* : the current slider value
276-
277-
*vline* : a :class:`matplotlib.lines.Line2D` instance
278-
representing the initial value of the slider
279-
280-
*poly* : A :class:`matplotlib.patches.Polygon` instance
281-
which is the slider knob
282-
283-
*valfmt* : the format string for formatting the slider text
284-
285-
*label* : a :class:`matplotlib.text.Text` instance
286-
for the slider label
287-
288-
*closedmin* : whether the slider is closed on the minimum
289-
290-
*closedmax* : whether the slider is closed on the maximum
291-
292-
*slidermin* : another slider - if not *None*, this slider must be
293-
greater than *slidermin*
294-
295-
*slidermax* : another slider - if not *None*, this slider must be
296-
less than *slidermax*
297-
298-
*dragging* : allow for mouse dragging on slider
269+
Create a slider from `valmin` to `valmax` in axes `ax`. For the slider to
270+
remain responsive you must maintain a reference to it.
299271
300272
Call :meth:`on_changed` to connect to the slider event
301273
"""
302274
def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',
303275
closedmin=True, closedmax=True, slidermin=None,
304276
slidermax=None, dragging=True, **kwargs):
305277
"""
306-
Create a slider from *valmin* to *valmax* in axes *ax*.
307-
308-
Additional kwargs are passed on to ``self.poly`` which is the
309-
:class:`matplotlib.patches.Rectangle` that draws the slider
310-
knob. See the :class:`matplotlib.patches.Rectangle` documentation for
311-
valid property names (e.g., *facecolor*, *edgecolor*, *alpha*, ...).
312-
313278
Parameters
314279
----------
315280
ax : Axes
316-
The Axes to put the slider in
281+
The Axes to put the slider in.
317282
318283
label : str
319-
Slider label
284+
Slider label.
320285
321286
valmin : float
322-
The minimum value of the slider
287+
The minimum value of the slider.
323288
324289
valmax : float
325-
The maximum value of the slider
326-
327-
valinit : float
328-
The slider initial position
290+
The maximum value of the slider.
329291
330-
label : str
331-
The slider label
292+
valinit : float, optional, default: 0.5
293+
The slider initial position.
332294
333-
valfmt : str
334-
Used to format the slider value, fprint format string
295+
valfmt : str, optional, default: "%1.2f"
296+
Used to format the slider value, fprint format string.
335297
336-
closedmin : bool
337-
Indicate whether the slider interval is closed on the bottom
298+
closedmin : bool, optional, default: True
299+
Indicate whether the slider interval is closed on the bottom.
338300
339-
closedmax : bool
340-
Indicate whether the slider interval is closed on the top
301+
closedmax : bool, optional, default: True
302+
Indicate whether the slider interval is closed on the top.
341303
342-
slidermin : Slider or None
304+
slidermin : Slider, optional, default: None
343305
Do not allow the current slider to have a value less than
344-
`slidermin`
306+
the value of the Slider `slidermin`.
345307
346-
slidermax : Slider or None
308+
slidermax : Slider, optional, default: None
347309
Do not allow the current slider to have a value greater than
348-
`slidermax`
349-
310+
the value of the Slider `slidermax`.
350311
351-
dragging : bool
352-
if the slider can be dragged by the mouse
312+
dragging : bool, optional, default: True
313+
If True the slider can be dragged by the mouse.
353314
315+
Notes
316+
-----
317+
Additional kwargs are passed on to ``self.poly`` which is the
318+
:class:`~matplotlib.patches.Rectangle` that draws the slider
319+
knob. See the :class:`~matplotlib.patches.Rectangle` documentation for
320+
valid property names (e.g., `facecolor`, `edgecolor`, `alpha`).
354321
"""
355322
AxesWidget.__init__(self, ax)
356323

324+
if slidermin is not None and not hasattr(slidermin, 'val'):
325+
raise ValueError("Argument slidermin ({}) has no 'val'"
326+
.format(type(slidermin)))
327+
if slidermax is not None and not hasattr(slidermax, 'val'):
328+
raise ValueError("Argument slidermax ({}) has no 'val'"
329+
.format(type(slidermax)))
330+
self.closedmin = closedmin
331+
self.closedmax = closedmax
332+
self.slidermin = slidermin
333+
self.slidermax = slidermax
334+
self.drag_active = False
357335
self.valmin = valmin
358336
self.valmax = valmax
337+
valinit = self._value_in_bounds(valinit)
359338
self.val = valinit
360339
self.valinit = valinit
361340
self.poly = ax.axvspan(valmin, valinit, 0, 1, **kwargs)
362-
363341
self.vline = ax.axvline(valinit, 0, 1, color='r', lw=1)
364342

365343
self.valfmt = valfmt
@@ -384,11 +362,29 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',
384362
self.cnt = 0
385363
self.observers = {}
386364

387-
self.closedmin = closedmin
388-
self.closedmax = closedmax
389-
self.slidermin = slidermin
390-
self.slidermax = slidermax
391-
self.drag_active = False
365+
self.set_val(valinit)
366+
367+
def _value_in_bounds(self, val):
368+
""" Makes sure self.val is with given bounds."""
369+
if val <= self.valmin:
370+
if not self.closedmin:
371+
return
372+
val = self.valmin
373+
elif val >= self.valmax:
374+
if not self.closedmax:
375+
return
376+
val = self.valmax
377+
378+
if self.slidermin is not None and val <= self.slidermin.val:
379+
if not self.closedmin:
380+
return
381+
val = self.slidermin.val
382+
383+
if self.slidermax is not None and val >= self.slidermax.val:
384+
if not self.closedmax:
385+
return
386+
val = self.slidermax.val
387+
return val
392388

393389
def _update(self, event):
394390
"""update the slider position"""
@@ -411,28 +407,8 @@ def _update(self, event):
411407
self.drag_active = False
412408
event.canvas.release_mouse(self.ax)
413409
return
414-
415410
val = event.xdata
416-
if val <= self.valmin:
417-
if not self.closedmin:
418-
return
419-
val = self.valmin
420-
elif val >= self.valmax:
421-
if not self.closedmax:
422-
return
423-
val = self.valmax
424-
425-
if self.slidermin is not None and val <= self.slidermin.val:
426-
if not self.closedmin:
427-
return
428-
val = self.slidermin.val
429-
430-
if self.slidermax is not None and val >= self.slidermax.val:
431-
if not self.closedmax:
432-
return
433-
val = self.slidermax.val
434-
435-
self.set_val(val)
411+
self.set_val(self._value_in_bounds(val))
436412

437413
def set_val(self, val):
438414
xy = self.poly.xy

0 commit comments

Comments
 (0)