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

Merged
merged 10 commits into from Feb 25, 2017
@@ -13,6 +13,8 @@
from numpy.testing import assert_allclose
+import pytest
+
def get_ax():
fig, ax = plt.subplots(1, 1)
@@ -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
View
@@ -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)
@NelleV

NelleV Feb 23, 2017

Contributor

👍

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
@@ -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"""
@@ -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