Skip to content

Update Slider docs and type check slidermin and slidermax. #8134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 25, 2017
38 changes: 38 additions & 0 deletions lib/matplotlib/tests/test_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

from numpy.testing import assert_allclose

import pytest


def get_ax():
fig, ax = plt.subplots(1, 1)
Expand Down Expand Up @@ -275,3 +277,39 @@ def test_check_radio_buttons_image():
widgets.RadioButtons(rax1, ('Radio 1', 'Radio 2', 'Radio 3'))
widgets.CheckButtons(rax2, ('Check 1', 'Check 2', 'Check 3'),
(False, True, True))


def test_slider_slidermin_slidermax_invalid():
fig, ax = plt.subplots()
# test min/max with floats
with pytest.raises(ValueError):
widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
slidermin=10.0)
with pytest.raises(ValueError):
widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
slidermax=10.0)


def test_slider_slidermin_slidermax():
fig, ax = plt.subplots()
slider_ = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
valinit=5.0)

slider = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
valinit=1.0, slidermin=slider_)
assert slider.val == slider_.val

slider = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
valinit=10.0, slidermax=slider_)
assert slider.val == slider_.val


def test_slider_valmin_valmax():
fig, ax = plt.subplots()
slider = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
valinit=-10.0)
assert slider.val == slider.valmin

slider = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
valinit=25.0)
assert slider.val == slider.valmax
148 changes: 62 additions & 86 deletions lib/matplotlib/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,100 +266,78 @@ class Slider(AxesWidget):
"""
A slider representing a floating point range.

For the slider to remain responsive you must maintain a
reference to it.

The following attributes are defined
*ax* : the slider :class:`matplotlib.axes.Axes` instance

*val* : the current slider value

*vline* : a :class:`matplotlib.lines.Line2D` instance
representing the initial value of the slider

*poly* : A :class:`matplotlib.patches.Polygon` instance
which is the slider knob

*valfmt* : the format string for formatting the slider text

*label* : a :class:`matplotlib.text.Text` instance
for the slider label

*closedmin* : whether the slider is closed on the minimum

*closedmax* : whether the slider is closed on the maximum

*slidermin* : another slider - if not *None*, this slider must be
greater than *slidermin*

*slidermax* : another slider - if not *None*, this slider must be
less than *slidermax*

*dragging* : allow for mouse dragging on slider
Create a slider from `valmin` to `valmax` in axes `ax`. For the slider to
remain responsive you must maintain a reference to it.

Call :meth:`on_changed` to connect to the slider event
"""
def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',
closedmin=True, closedmax=True, slidermin=None,
slidermax=None, dragging=True, **kwargs):
"""
Create a slider from *valmin* to *valmax* in axes *ax*.

Additional kwargs are passed on to ``self.poly`` which is the
:class:`matplotlib.patches.Rectangle` that draws the slider
knob. See the :class:`matplotlib.patches.Rectangle` documentation for
valid property names (e.g., *facecolor*, *edgecolor*, *alpha*, ...).

Parameters
----------
ax : Axes
The Axes to put the slider in
The Axes to put the slider in.

label : str
Slider label
Slider label.

valmin : float
The minimum value of the slider
The minimum value of the slider.

valmax : float
The maximum value of the slider

valinit : float
The slider initial position
The maximum value of the slider.

label : str
The slider label
valinit : float, optional, default: 0.5
The slider initial position.

valfmt : str
Used to format the slider value, fprint format string
valfmt : str, optional, default: "%1.2f"
Used to format the slider value, fprint format string.

closedmin : bool
Indicate whether the slider interval is closed on the bottom
closedmin : bool, optional, default: True
Indicate whether the slider interval is closed on the bottom.

closedmax : bool
Indicate whether the slider interval is closed on the top
closedmax : bool, optional, default: True
Indicate whether the slider interval is closed on the top.

slidermin : Slider or None
slidermin : Slider, optional, default: None
Do not allow the current slider to have a value less than
`slidermin`
the value of the Slider `slidermin`.

slidermax : Slider or None
slidermax : Slider, optional, default: None
Do not allow the current slider to have a value greater than
`slidermax`

the value of the Slider `slidermax`.

dragging : bool
if the slider can be dragged by the mouse
dragging : bool, optional, default: True
If True the slider can be dragged by the mouse.

Notes
-----
Additional kwargs are passed on to ``self.poly`` which is the
:class:`~matplotlib.patches.Rectangle` that draws the slider
knob. See the :class:`~matplotlib.patches.Rectangle` documentation for
valid property names (e.g., `facecolor`, `edgecolor`, `alpha`).
"""
AxesWidget.__init__(self, ax)

if slidermin is not None and not hasattr(slidermin, 'val'):
raise ValueError("Argument slidermin ({}) has no 'val'"
.format(type(slidermin)))
if slidermax is not None and not hasattr(slidermax, 'val'):
raise ValueError("Argument slidermax ({}) has no 'val'"
.format(type(slidermax)))
self.closedmin = closedmin
self.closedmax = closedmax
self.slidermin = slidermin
self.slidermax = slidermax
self.drag_active = False
self.valmin = valmin
self.valmax = valmax
valinit = self._value_in_bounds(valinit)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

self.val = valinit
self.valinit = valinit
self.poly = ax.axvspan(valmin, valinit, 0, 1, **kwargs)

self.vline = ax.axvline(valinit, 0, 1, color='r', lw=1)

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

self.closedmin = closedmin
self.closedmax = closedmax
self.slidermin = slidermin
self.slidermax = slidermax
self.drag_active = False
self.set_val(valinit)

def _value_in_bounds(self, val):
""" Makes sure self.val is with given bounds."""
if val <= self.valmin:
if not self.closedmin:
return
val = self.valmin
elif val >= self.valmax:
if not self.closedmax:
return
val = self.valmax

if self.slidermin is not None and val <= self.slidermin.val:
if not self.closedmin:
return
val = self.slidermin.val

if self.slidermax is not None and val >= self.slidermax.val:
if not self.closedmax:
return
val = self.slidermax.val
return val

def _update(self, event):
"""update the slider position"""
Expand All @@ -411,28 +407,8 @@ def _update(self, event):
self.drag_active = False
event.canvas.release_mouse(self.ax)
return

val = event.xdata
if val <= self.valmin:
if not self.closedmin:
return
val = self.valmin
elif val >= self.valmax:
if not self.closedmax:
return
val = self.valmax

if self.slidermin is not None and val <= self.slidermin.val:
if not self.closedmin:
return
val = self.slidermin.val

if self.slidermax is not None and val >= self.slidermax.val:
if not self.closedmax:
return
val = self.slidermax.val

self.set_val(val)
self.set_val(self._value_in_bounds(val))

def set_val(self, val):
xy = self.poly.xy
Expand Down