Skip to content

Commit 820bea6

Browse files
williamjameshandleytimhoffm
authored andcommitted
Adjusted matplotlib.widgets.Slider to have optional vertical orientatation (matplotlib#10746)
* Adjusted matplotlib.widgets.Slider to have optional vertical orientation. The slider widget now takes an optional argument (orientation) with values 'h' or 'v, which defaults to 'h'. Argument checking is in keeping with the existing code, and the actual changes to the source are minimal, replacing hspans, hlines and xdata with a if switch to vspans and vlines and ydata. * Changed 'h' and 'v' to 'horizontal' and 'vertical' * Typo corrections so that code is PEP-8 compliant I forgot that I had not yet installed pyflakes and pylint on my new system, so my vim syntax checker didn't pick it up. * Added test for horizontal and vertical orientations * Corrected typo in my modifications, and made test_widgets.py pep compliant regarding line-continuing indentation * Adjusted docstring to follow numpydoc * Added whats new * Moved what's new section to doc/users/whats_new.rst * Changed is to ==, and sets to lists
1 parent 52fa0ee commit 820bea6

File tree

3 files changed

+70
-14
lines changed

3 files changed

+70
-14
lines changed

doc/users/whats_new.rst

+9
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,15 @@ and the title will not be moved via this algorithm.
192192

193193

194194

195+
Adjusted ``matplotlib.widgets.Slider`` to have vertical orientation
196+
-------------------------------------------------------------------
197+
198+
The :class:`matplotlib.widgets.Slider` widget now takes an optional argument
199+
``orientation`` which indicates the direction (``'horizontal'`` or
200+
``'vertical'``) that the slider should take.
201+
202+
203+
195204
New convenience methods for GridSpec
196205
------------------------------------
197206

lib/matplotlib/tests/test_widgets.py

+14
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,20 @@ def test_slider_valmin_valmax():
319319
assert slider.val == slider.valmax
320320

321321

322+
def test_slider_horizontal_vertical():
323+
fig, ax = plt.subplots()
324+
slider = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
325+
valinit=12.0, orientation='horizontal')
326+
slider.set_val(10.0)
327+
assert slider.val == 10.0
328+
329+
fig, ax = plt.subplots()
330+
slider = widgets.Slider(ax=ax, label='', valmin=0.0, valmax=24.0,
331+
valinit=12.0, orientation='vertical')
332+
slider.set_val(10.0)
333+
assert slider.val == 10.0
334+
335+
322336
def check_polygon_selector(event_sequence, expected_result, selections_count):
323337
"""Helper function to test Polygon Selector
324338

lib/matplotlib/widgets.py

+47-14
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,8 @@ class Slider(AxesWidget):
268268
"""
269269
def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',
270270
closedmin=True, closedmax=True, slidermin=None,
271-
slidermax=None, dragging=True, valstep=None, **kwargs):
271+
slidermax=None, dragging=True, valstep=None,
272+
orientation='horizontal', **kwargs):
272273
"""
273274
Parameters
274275
----------
@@ -310,6 +311,9 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',
310311
valstep : float, optional, default: None
311312
If given, the slider will snap to multiples of `valstep`.
312313
314+
orientation : str, 'horizontal' or 'vertical', default: 'horizontal'
315+
The orientation of the slider.
316+
313317
Notes
314318
-----
315319
Additional kwargs are passed on to ``self.poly`` which is the
@@ -325,6 +329,11 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',
325329
if slidermax is not None and not hasattr(slidermax, 'val'):
326330
raise ValueError("Argument slidermax ({}) has no 'val'"
327331
.format(type(slidermax)))
332+
if orientation not in ['horizontal', 'vertical']:
333+
raise ValueError("Argument orientation ({}) must be either"
334+
"'horizontal' or 'vertical'".format(orientation))
335+
336+
self.orientation = orientation
328337
self.closedmin = closedmin
329338
self.closedmax = closedmax
330339
self.slidermin = slidermin
@@ -338,27 +347,44 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',
338347
valinit = valmin
339348
self.val = valinit
340349
self.valinit = valinit
341-
self.poly = ax.axvspan(valmin, valinit, 0, 1, **kwargs)
342-
self.vline = ax.axvline(valinit, 0, 1, color='r', lw=1)
350+
if orientation == 'vertical':
351+
self.poly = ax.axhspan(valmin, valinit, 0, 1, **kwargs)
352+
self.hline = ax.axhline(valinit, 0, 1, color='r', lw=1)
353+
else:
354+
self.poly = ax.axvspan(valmin, valinit, 0, 1, **kwargs)
355+
self.vline = ax.axvline(valinit, 0, 1, color='r', lw=1)
343356

344357
self.valfmt = valfmt
345358
ax.set_yticks([])
346-
ax.set_xlim((valmin, valmax))
359+
if orientation == 'vertical':
360+
ax.set_ylim((valmin, valmax))
361+
else:
362+
ax.set_xlim((valmin, valmax))
347363
ax.set_xticks([])
348364
ax.set_navigate(False)
349365

350366
self.connect_event('button_press_event', self._update)
351367
self.connect_event('button_release_event', self._update)
352368
if dragging:
353369
self.connect_event('motion_notify_event', self._update)
354-
self.label = ax.text(-0.02, 0.5, label, transform=ax.transAxes,
355-
verticalalignment='center',
356-
horizontalalignment='right')
370+
if orientation == 'vertical':
371+
self.label = ax.text(0.5, 1.02, label, transform=ax.transAxes,
372+
verticalalignment='bottom',
373+
horizontalalignment='center')
374+
375+
self.valtext = ax.text(0.5, -0.02, valfmt % valinit,
376+
transform=ax.transAxes,
377+
verticalalignment='top',
378+
horizontalalignment='center')
379+
else:
380+
self.label = ax.text(-0.02, 0.5, label, transform=ax.transAxes,
381+
verticalalignment='center',
382+
horizontalalignment='right')
357383

358-
self.valtext = ax.text(1.02, 0.5, valfmt % valinit,
359-
transform=ax.transAxes,
360-
verticalalignment='center',
361-
horizontalalignment='left')
384+
self.valtext = ax.text(1.02, 0.5, valfmt % valinit,
385+
transform=ax.transAxes,
386+
verticalalignment='center',
387+
horizontalalignment='left')
362388

363389
self.cnt = 0
364390
self.observers = {}
@@ -412,7 +438,10 @@ def _update(self, event):
412438
self.drag_active = False
413439
event.canvas.release_mouse(self.ax)
414440
return
415-
val = self._value_in_bounds(event.xdata)
441+
if self.orientation == 'vertical':
442+
val = self._value_in_bounds(event.ydata)
443+
else:
444+
val = self._value_in_bounds(event.xdata)
416445
if val not in [None, self.val]:
417446
self.set_val(val)
418447

@@ -425,8 +454,12 @@ def set_val(self, val):
425454
val : float
426455
"""
427456
xy = self.poly.xy
428-
xy[2] = val, 1
429-
xy[3] = val, 0
457+
if self.orientation == 'vertical':
458+
xy[1] = 0, val
459+
xy[2] = 1, val
460+
else:
461+
xy[2] = val, 1
462+
xy[3] = val, 0
430463
self.poly.xy = xy
431464
self.valtext.set_text(self.valfmt % val)
432465
if self.drawon:

0 commit comments

Comments
 (0)