From 7da0279fd3b2785e8642f1ba462aa7c721b79058 Mon Sep 17 00:00:00 2001 From: ianhi Date: Sat, 9 Jan 2021 00:41:16 -0500 Subject: [PATCH 1/8] Change styling of slider widgets Goal is to add a clear handle for the user to grab and to provide visual feedback via color change of when the slider has been grabbed. Simplify slider background rectangles rename bkd -> track + change default color to lightgrey lint remove facecolor from snap demo example Don't change handle color on grab. correct errors in slider docstrings Co-Authored-By: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- examples/widgets/slider_demo.py | 9 +- examples/widgets/slider_snap_demo.py | 7 +- lib/matplotlib/tests/test_widgets.py | 8 +- lib/matplotlib/widgets.py | 148 +++++++++++++++++++++++---- 4 files changed, 137 insertions(+), 35 deletions(-) diff --git a/examples/widgets/slider_demo.py b/examples/widgets/slider_demo.py index aa33315d3db4..ffe66279a77b 100644 --- a/examples/widgets/slider_demo.py +++ b/examples/widgets/slider_demo.py @@ -32,14 +32,11 @@ def f(t, amplitude, frequency): line, = plt.plot(t, f(t, init_amplitude, init_frequency), lw=2) ax.set_xlabel('Time [s]') -axcolor = 'lightgoldenrodyellow' -ax.margins(x=0) - # adjust the main plot to make room for the sliders plt.subplots_adjust(left=0.25, bottom=0.25) # Make a horizontal slider to control the frequency. -axfreq = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor) +axfreq = plt.axes([0.25, 0.1, 0.65, 0.03]) freq_slider = Slider( ax=axfreq, label='Frequency [Hz]', @@ -49,7 +46,7 @@ def f(t, amplitude, frequency): ) # Make a vertically oriented slider to control the amplitude -axamp = plt.axes([0.1, 0.25, 0.0225, 0.63], facecolor=axcolor) +axamp = plt.axes([0.1, 0.25, 0.0225, 0.63]) amp_slider = Slider( ax=axamp, label="Amplitude", @@ -72,7 +69,7 @@ def update(val): # Create a `matplotlib.widgets.Button` to reset the sliders to initial values. resetax = plt.axes([0.8, 0.025, 0.1, 0.04]) -button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975') +button = Button(resetax, 'Reset', hovercolor='0.975') def reset(event): diff --git a/examples/widgets/slider_snap_demo.py b/examples/widgets/slider_snap_demo.py index e985f84ca7ac..f02dd9a6b961 100644 --- a/examples/widgets/slider_snap_demo.py +++ b/examples/widgets/slider_snap_demo.py @@ -28,9 +28,8 @@ plt.subplots_adjust(bottom=0.25) l, = plt.plot(t, s, lw=2) -slider_bkd_color = 'lightgoldenrodyellow' -ax_freq = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=slider_bkd_color) -ax_amp = plt.axes([0.25, 0.15, 0.65, 0.03], facecolor=slider_bkd_color) +ax_freq = plt.axes([0.25, 0.1, 0.65, 0.03]) +ax_amp = plt.axes([0.25, 0.15, 0.65, 0.03]) # define the values to use for snapping allowed_amplitudes = np.concatenate([np.linspace(.1, 5, 100), [6, 7, 8, 9]]) @@ -60,7 +59,7 @@ def update(val): samp.on_changed(update) ax_reset = plt.axes([0.8, 0.025, 0.1, 0.04]) -button = Button(ax_reset, 'Reset', color=slider_bkd_color, hovercolor='0.975') +button = Button(ax_reset, 'Reset', hovercolor='0.975') def reset(event): diff --git a/lib/matplotlib/tests/test_widgets.py b/lib/matplotlib/tests/test_widgets.py index f2ac7749d6ea..6784ac2ab60e 100644 --- a/lib/matplotlib/tests/test_widgets.py +++ b/lib/matplotlib/tests/test_widgets.py @@ -332,7 +332,7 @@ def test_slider_horizontal_vertical(): assert slider.val == 10 # check the dimension of the slider patch in axes units box = slider.poly.get_extents().transformed(ax.transAxes.inverted()) - assert_allclose(box.bounds, [0, 0, 10/24, 1]) + assert_allclose(box.bounds, [0, .25, 10/24, .5]) fig, ax = plt.subplots() slider = widgets.Slider(ax=ax, label='', valmin=0, valmax=24, @@ -341,7 +341,7 @@ def test_slider_horizontal_vertical(): assert slider.val == 10 # check the dimension of the slider patch in axes units box = slider.poly.get_extents().transformed(ax.transAxes.inverted()) - assert_allclose(box.bounds, [0, 0, 1, 10/24]) + assert_allclose(box.bounds, [.25, 0, .5, 10/24]) @pytest.mark.parametrize("orientation", ["horizontal", "vertical"]) @@ -358,7 +358,7 @@ def test_range_slider(orientation): valinit=[0.1, 0.34] ) box = slider.poly.get_extents().transformed(ax.transAxes.inverted()) - assert_allclose(box.get_points().flatten()[idx], [0.1, 0, 0.34, 1]) + assert_allclose(box.get_points().flatten()[idx], [0.1, 0.25, 0.34, 0.75]) # Check initial value is set correctly assert_allclose(slider.val, (0.1, 0.34)) @@ -366,7 +366,7 @@ def test_range_slider(orientation): slider.set_val((0.2, 0.6)) assert_allclose(slider.val, (0.2, 0.6)) box = slider.poly.get_extents().transformed(ax.transAxes.inverted()) - assert_allclose(box.get_points().flatten()[idx], [0.2, 0, 0.6, 1]) + assert_allclose(box.get_points().flatten()[idx], [0.2, .25, 0.6, .75]) slider.set_val((0.2, 0.1)) assert_allclose(slider.val, (0.1, 0.2)) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 7d2243f6c553..5050f73c9df0 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -267,9 +267,9 @@ def __init__(self, ax, orientation, closedmin, closedmax, self._fmt.set_useOffset(False) # No additive offset. self._fmt.set_useMathText(True) # x sign before multiplicative offset. - ax.set_xticks([]) - ax.set_yticks([]) + ax.set_axis_off() ax.set_navigate(False) + self.connect_event("button_press_event", self._update) self.connect_event("button_release_event", self._update) if dragging: @@ -329,7 +329,9 @@ class Slider(SliderBase): def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, closedmin=True, closedmax=True, slidermin=None, slidermax=None, dragging=True, valstep=None, - orientation='horizontal', *, initcolor='r', **kwargs): + orientation='horizontal', *, initcolor='r', + track_color='lightgrey', handle_facecolor='white', + handle_edgecolor='.75', handle_size=10, **kwargs): """ Parameters ---------- @@ -380,6 +382,19 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, The color of the line at the *valinit* position. Set to ``'none'`` for no line. + track_color : color, default: 'lightgrey' + The color of the background track. The track is accessible for + further styling via the *track* attribute. + + handle_facecolor : color, default: 'white' + The facecolor of the circular slider handle. + + handle_edgecolor : color, default: '.75' + The edgecolor of the circle slider handle. + + handle_size : int, default: 10 + The size of the circular slider handle in points. + Notes ----- Additional kwargs are passed on to ``self.poly`` which is the @@ -404,11 +419,33 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, self.val = valinit self.valinit = valinit if orientation == 'vertical': - self.poly = ax.axhspan(valmin, valinit, 0, 1, **kwargs) - self.hline = ax.axhline(valinit, 0, 1, color=initcolor, lw=1) + self.track = Rectangle( + (.25, 0), .5, 1, + transform=ax.transAxes, + facecolor=track_color + ) + ax.add_patch(self.track) + self.poly = ax.axhspan(valmin, valinit, .25, .75, **kwargs) + self.hline = ax.axhline(valinit, .25, .75, color=initcolor, lw=1) + handleXY = [[0.5], [valinit]] else: - self.poly = ax.axvspan(valmin, valinit, 0, 1, **kwargs) - self.vline = ax.axvline(valinit, 0, 1, color=initcolor, lw=1) + self.track = Rectangle( + (0, .25), 1, .5, + transform=ax.transAxes, + facecolor=track_color + ) + ax.add_patch(self.track) + self.poly = ax.axvspan(valmin, valinit, .25, .75, **kwargs) + self.vline = ax.axvline(valinit, .25, .75, color=initcolor, lw=1) + handleXY = [[valinit], [0.5]] + self._handle, = ax.plot( + *handleXY, + "o", + markersize=handle_size, + markeredgecolor=handle_edgecolor, + markerfacecolor=handle_facecolor, + clip_on=False + ) if orientation == 'vertical': self.label = ax.text(0.5, 1.02, label, transform=ax.transAxes, @@ -499,11 +536,13 @@ def set_val(self, val): """ xy = self.poly.xy if self.orientation == 'vertical': - xy[1] = 0, val - xy[2] = 1, val + xy[1] = .25, val + xy[2] = .75, val + self._handle.set_ydata([val]) else: - xy[2] = val, 1 - xy[3] = val, 0 + xy[2] = val, .75 + xy[3] = val, .25 + self._handle.set_xdata([val]) self.poly.xy = xy self.valtext.set_text(self._format(val)) if self.drawon: @@ -558,6 +597,10 @@ def __init__( dragging=True, valstep=None, orientation="horizontal", + track_color='lightgrey', + handle_facecolor='white', + handle_edgecolor='.75', + handle_size=10, **kwargs, ): """ @@ -598,6 +641,19 @@ def __init__( orientation : {'horizontal', 'vertical'}, default: 'horizontal' The orientation of the slider. + track_color : color, default: 'lightgrey' + The color of the background track. The track is accessible for + further styling via the *track* attribute. + + handle_facecolor : color, default: 'white' + The facecolor of the circular slider handle. + + handle_edgecolor : color, default: '.75' + The edgecolor of the circular slider handles. + + handle_size : int, default: 10 + The size of the circular slider handles in points. + Notes ----- Additional kwargs are passed on to ``self.poly`` which is the @@ -620,9 +676,43 @@ def __init__( self.val = valinit self.valinit = valinit if orientation == "vertical": + self.track = Rectangle( + (.25, 0), .5, 2, + transform=ax.transAxes, + facecolor=track_color + ) + ax.add_patch(self.track) self.poly = ax.axhspan(valinit[0], valinit[1], 0, 1, **kwargs) + handleXY_1 = [.5, valinit[0]] + handleXY_2 = [.5, valinit[1]] else: + self.track = Rectangle( + (0, .25), 1, .5, + transform=ax.transAxes, + facecolor=track_color + ) + ax.add_patch(self.track) self.poly = ax.axvspan(valinit[0], valinit[1], 0, 1, **kwargs) + handleXY_1 = [valinit[0], .5] + handleXY_2 = [valinit[1], .5] + self._handles = [ + ax.plot( + *handleXY_1, + "o", + markersize=handle_size, + markeredgecolor=handle_edgecolor, + markerfacecolor=handle_facecolor, + clip_on=False + )[0], + ax.plot( + *handleXY_2, + "o", + markersize=handle_size, + markeredgecolor=handle_edgecolor, + markerfacecolor=handle_facecolor, + clip_on=False + )[0] + ] if orientation == "vertical": self.label = ax.text( @@ -661,6 +751,7 @@ def __init__( horizontalalignment="left", ) + self._active_handle = None self.set_val(valinit) def _min_in_bounds(self, min): @@ -698,6 +789,8 @@ def _update_val_from_pos(self, pos): else: val = self._max_in_bounds(pos) self.set_max(val) + if self._active_handle: + self._active_handle.set_xdata([val]) def _update(self, event): """Update the slider position.""" @@ -716,7 +809,20 @@ def _update(self, event): ): self.drag_active = False event.canvas.release_mouse(self.ax) + self._active_handle = None return + + # determine which handle was grabbed + handle = self._handles[ + np.argmin( + np.abs([h.get_xdata()[0] - event.xdata for h in self._handles]) + ) + ] + # these checks ensure smooth behavior if the handles swap which one + # has a higher value. i.e. if one is dragged over and past the other. + if handle is not self._active_handle: + self._active_handle = handle + if self.orientation == "vertical": self._update_val_from_pos(event.ydata) else: @@ -773,17 +879,17 @@ def set_val(self, val): val[1] = self._max_in_bounds(val[1]) xy = self.poly.xy if self.orientation == "vertical": - xy[0] = 0, val[0] - xy[1] = 0, val[1] - xy[2] = 1, val[1] - xy[3] = 1, val[0] - xy[4] = 0, val[0] + xy[0] = .25, val[0] + xy[1] = .25, val[1] + xy[2] = .75, val[1] + xy[3] = .75, val[0] + xy[4] = .25, val[0] else: - xy[0] = val[0], 0 - xy[1] = val[0], 1 - xy[2] = val[1], 1 - xy[3] = val[1], 0 - xy[4] = val[0], 0 + xy[0] = val[0], .25 + xy[1] = val[0], .75 + xy[2] = val[1], .75 + xy[3] = val[1], .25 + xy[4] = val[0], .25 self.poly.xy = xy self.valtext.set_text(self._format(val)) if self.drawon: From 61304ad1216d3fb5b59dae94dda1f6b4e826b235 Mon Sep 17 00:00:00 2001 From: Ian Hunt-Isaak Date: Tue, 12 Jan 2021 17:49:44 -0500 Subject: [PATCH 2/8] correctly specify the type of the slider `poly` attribute --- lib/matplotlib/widgets.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 5050f73c9df0..1a8d3de88798 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -398,8 +398,8 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, Notes ----- Additional kwargs are passed on to ``self.poly`` which is the - `~matplotlib.patches.Rectangle` that draws the slider knob. See the - `.Rectangle` documentation for valid property names (``facecolor``, + `~matplotlib.patches.Polygon` that draws the slider knob. See the + `.Polygon` documentation for valid property names (``facecolor``, ``edgecolor``, ``alpha``, etc.). """ super().__init__(ax, orientation, closedmin, closedmax, @@ -657,8 +657,8 @@ def __init__( Notes ----- Additional kwargs are passed on to ``self.poly`` which is the - `~matplotlib.patches.Rectangle` that draws the slider knob. See the - `.Rectangle` documentation for valid property names (``facecolor``, + `~matplotlib.patches.Polygon` that draws the slider knob. See the + `.Polygon` documentation for valid property names (``facecolor``, ``edgecolor``, ``alpha``, etc.). """ super().__init__(ax, orientation, closedmin, closedmax, From 776af75fde690e05a3faece29a32f92de4e332ee Mon Sep 17 00:00:00 2001 From: Ian Hunt-Isaak Date: Fri, 22 Jan 2021 23:41:19 -0500 Subject: [PATCH 3/8] Consolidate slider handle styling kwargs Co-Authored-By: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- lib/matplotlib/widgets.py | 69 +++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 1a8d3de88798..c8d26b6b653b 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -330,8 +330,7 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, closedmin=True, closedmax=True, slidermin=None, slidermax=None, dragging=True, valstep=None, orientation='horizontal', *, initcolor='r', - track_color='lightgrey', handle_facecolor='white', - handle_edgecolor='.75', handle_size=10, **kwargs): + track_color='lightgrey', handle_style=None, **kwargs): """ Parameters ---------- @@ -386,14 +385,16 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, The color of the background track. The track is accessible for further styling via the *track* attribute. - handle_facecolor : color, default: 'white' - The facecolor of the circular slider handle. + handle_style : dict + Properties of the slider handle. Supported values are - handle_edgecolor : color, default: '.75' - The edgecolor of the circle slider handle. - - handle_size : int, default: 10 - The size of the circular slider handle in points. + ========= ===== ======= ======================================== + Key Value Default Description + ========= ===== ======= ======================================== + facecolor color 'white' The facecolor of the slider handle. + edgecolor color '.75' The edgecolor of the slider handle. + size int 10 The size of the slider handle in points. + ========= ===== ======= ======================================== Notes ----- @@ -418,6 +419,15 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, valinit = valmin self.val = valinit self.valinit = valinit + + marker_props = {} + defaults = {'facecolor':'white', 'edgecolor':'.75', 'size':10} + if handle_style is not None: + for k in ['facecolor', 'edgecolor', 'size']: + marker_props[f'marker{k}'] = handle_style.get(k, defaults[k]) + else: + marker_props = {f'marker{k}': v for k, v in defaults.items()} + if orientation == 'vertical': self.track = Rectangle( (.25, 0), .5, 1, @@ -441,9 +451,7 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, self._handle, = ax.plot( *handleXY, "o", - markersize=handle_size, - markeredgecolor=handle_edgecolor, - markerfacecolor=handle_facecolor, + **marker_props, clip_on=False ) @@ -598,9 +606,7 @@ def __init__( valstep=None, orientation="horizontal", track_color='lightgrey', - handle_facecolor='white', - handle_edgecolor='.75', - handle_size=10, + handle_style=None, **kwargs, ): """ @@ -645,14 +651,16 @@ def __init__( The color of the background track. The track is accessible for further styling via the *track* attribute. - handle_facecolor : color, default: 'white' - The facecolor of the circular slider handle. + handle_style : dict + Properties of the slider handles. Supported values are - handle_edgecolor : color, default: '.75' - The edgecolor of the circular slider handles. - - handle_size : int, default: 10 - The size of the circular slider handles in points. + ========= ===== ======= ========================================= + Key Value Default Description + ========= ===== ======= ========================================= + facecolor color 'white' The facecolor of the slider handles. + edgecolor color '.75' The edgecolor of the slider handles. + size int 10 The size of the slider handles in points. + ========= ===== ======= ========================================= Notes ----- @@ -675,6 +683,15 @@ def __init__( valinit = self._value_in_bounds(valinit) self.val = valinit self.valinit = valinit + + marker_props = {} + defaults = {'facecolor':'white', 'edgecolor':'.75', 'size':10} + if handle_style is not None: + for k in ['facecolor', 'edgecolor', 'size']: + marker_props[f'marker{k}'] = handle_style.get(k, defaults[k]) + else: + marker_props = {f'marker{k}': v for k, v in defaults.items()} + if orientation == "vertical": self.track = Rectangle( (.25, 0), .5, 2, @@ -699,17 +716,13 @@ def __init__( ax.plot( *handleXY_1, "o", - markersize=handle_size, - markeredgecolor=handle_edgecolor, - markerfacecolor=handle_facecolor, + **marker_props, clip_on=False )[0], ax.plot( *handleXY_2, "o", - markersize=handle_size, - markeredgecolor=handle_edgecolor, - markerfacecolor=handle_facecolor, + **marker_props, clip_on=False )[0] ] From 2f153b84cc510818943e574a380b17f6dc9f9584 Mon Sep 17 00:00:00 2001 From: Ian Hunt-Isaak Date: Mon, 15 Feb 2021 19:20:13 -0500 Subject: [PATCH 4/8] promote all keys to marker{key} Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- lib/matplotlib/widgets.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index c8d26b6b653b..275c4c01fec4 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -420,13 +420,8 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, self.val = valinit self.valinit = valinit - marker_props = {} defaults = {'facecolor':'white', 'edgecolor':'.75', 'size':10} - if handle_style is not None: - for k in ['facecolor', 'edgecolor', 'size']: - marker_props[f'marker{k}'] = handle_style.get(k, defaults[k]) - else: - marker_props = {f'marker{k}': v for k, v in defaults.items()} + marker_props = {f'marker{k}': v for k, v in {**defaults, **handle_style}} if orientation == 'vertical': self.track = Rectangle( From 1e3f6526d0f4868affe2a53cac7fb94d1acd0778 Mon Sep 17 00:00:00 2001 From: ianhi Date: Mon, 15 Feb 2021 19:26:47 -0500 Subject: [PATCH 5/8] expand doc string for handle_style --- lib/matplotlib/widgets.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 275c4c01fec4..6c909533bd52 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -386,7 +386,7 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, further styling via the *track* attribute. handle_style : dict - Properties of the slider handle. Supported values are + Properties of the slider handle. Default values are ========= ===== ======= ======================================== Key Value Default Description @@ -396,6 +396,10 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, size int 10 The size of the slider handle in points. ========= ===== ======= ======================================== + Other values will be transformed as marker{foo} and passed to the + `~.Line2D` constructor. e.g. ``handle_style = {'style'='x'}`` will + result in ``markerstyle = 'x'``. + Notes ----- Additional kwargs are passed on to ``self.poly`` which is the @@ -420,8 +424,10 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, self.val = valinit self.valinit = valinit - defaults = {'facecolor':'white', 'edgecolor':'.75', 'size':10} - marker_props = {f'marker{k}': v for k, v in {**defaults, **handle_style}} + defaults = {'facecolor': 'white', 'edgecolor': '.75', 'size': 10} + marker_props = { + f'marker{k}': v for k, v in {**defaults, **handle_style} + } if orientation == 'vertical': self.track = Rectangle( @@ -647,7 +653,7 @@ def __init__( further styling via the *track* attribute. handle_style : dict - Properties of the slider handles. Supported values are + Properties of the slider handles. Default values are ========= ===== ======= ========================================= Key Value Default Description @@ -657,6 +663,10 @@ def __init__( size int 10 The size of the slider handles in points. ========= ===== ======= ========================================= + Other values will be transformed as marker{foo} and passed to the + `~.Line2D` constructor. e.g. ``handle_style = {'style'='x'}`` will + result in ``markerstyle = 'x'``. + Notes ----- Additional kwargs are passed on to ``self.poly`` which is the @@ -679,13 +689,10 @@ def __init__( self.val = valinit self.valinit = valinit - marker_props = {} - defaults = {'facecolor':'white', 'edgecolor':'.75', 'size':10} - if handle_style is not None: - for k in ['facecolor', 'edgecolor', 'size']: - marker_props[f'marker{k}'] = handle_style.get(k, defaults[k]) - else: - marker_props = {f'marker{k}': v for k, v in defaults.items()} + defaults = {'facecolor': 'white', 'edgecolor': '.75', 'size': 10} + marker_props = { + f'marker{k}': v for k, v in {**defaults, **handle_style} + } if orientation == "vertical": self.track = Rectangle( From e160db4d3b58f124f26711bed68c06a30a676084 Mon Sep 17 00:00:00 2001 From: ianhi Date: Mon, 15 Feb 2021 20:24:00 -0500 Subject: [PATCH 6/8] fix errors in processing handle style --- lib/matplotlib/widgets.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 6c909533bd52..1d4350f5b24c 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -425,8 +425,9 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, self.valinit = valinit defaults = {'facecolor': 'white', 'edgecolor': '.75', 'size': 10} + handle_style = {} if handle_style is None else handle_style marker_props = { - f'marker{k}': v for k, v in {**defaults, **handle_style} + f'marker{k}': v for k, v in {**defaults, **handle_style}.items() } if orientation == 'vertical': @@ -690,8 +691,9 @@ def __init__( self.valinit = valinit defaults = {'facecolor': 'white', 'edgecolor': '.75', 'size': 10} + handle_style = {} if handle_style is None else handle_style marker_props = { - f'marker{k}': v for k, v in {**defaults, **handle_style} + f'marker{k}': v for k, v in {**defaults, **handle_style}.items() } if orientation == "vertical": From a7c4df6a4304cf71514858cd5f998e66588d8b7c Mon Sep 17 00:00:00 2001 From: Ian Hunt-Isaak Date: Sun, 7 Mar 2021 22:38:44 -0500 Subject: [PATCH 7/8] tune slider initline parameters to minimize asymmetry Co-Authored-By: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- lib/matplotlib/widgets.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 1d4350f5b24c..09573e45950e 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -438,7 +438,7 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, ) ax.add_patch(self.track) self.poly = ax.axhspan(valmin, valinit, .25, .75, **kwargs) - self.hline = ax.axhline(valinit, .25, .75, color=initcolor, lw=1) + self.hline = ax.axhline(valinit, .15, .85, color=initcolor, lw=1) handleXY = [[0.5], [valinit]] else: self.track = Rectangle( @@ -448,7 +448,12 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None, ) ax.add_patch(self.track) self.poly = ax.axvspan(valmin, valinit, .25, .75, **kwargs) - self.vline = ax.axvline(valinit, .25, .75, color=initcolor, lw=1) + # These asymmetric limits (.2, .9) minimize the asymmetry + # above and below the *poly* when rendered to pixels. + # This seems to be different for Horizontal and Vertical lines. + # For discussion see: + # https://github.com/matplotlib/matplotlib/pull/19265 + self.vline = ax.axvline(valinit, .2, .9, color=initcolor, lw=1) handleXY = [[valinit], [0.5]] self._handle, = ax.plot( *handleXY, From f5dcedd2e989fac1fbc7ab54d313f8698c5717c9 Mon Sep 17 00:00:00 2001 From: Ian Hunt-Isaak Date: Wed, 23 Jun 2021 17:17:38 -0400 Subject: [PATCH 8/8] Add whats new for new slider styles --- doc/users/next_whats_new/slider_styling.rst | 42 +++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 doc/users/next_whats_new/slider_styling.rst diff --git a/doc/users/next_whats_new/slider_styling.rst b/doc/users/next_whats_new/slider_styling.rst new file mode 100644 index 000000000000..f007954b4806 --- /dev/null +++ b/doc/users/next_whats_new/slider_styling.rst @@ -0,0 +1,42 @@ +Updated the appearance of Slider widgets +---------------------------------------- + +The appearance of `~.Slider` and `~.RangeSlider` widgets +were updated and given new styling parameters for the +added handles. + +.. plot:: + + import matplotlib.pyplot as plt + from matplotlib.widgets import Slider + + plt.figure(figsize=(4, 2)) + ax_old = plt.axes([0.2, 0.65, 0.65, 0.1]) + ax_new = plt.axes([0.2, 0.25, 0.65, 0.1]) + Slider(ax_new, "New", 0, 1) + + ax = ax_old + valmin = 0 + valinit = 0.5 + ax.set_xlim([0, 1]) + ax_old.axvspan(valmin, valinit, 0, 1) + ax.axvline(valinit, 0, 1, color="r", lw=1) + ax.set_xticks([]) + ax.set_yticks([]) + ax.text( + -0.02, + 0.5, + "Old", + transform=ax.transAxes, + verticalalignment="center", + horizontalalignment="right", + ) + + ax.text( + 1.02, + 0.5, + "0.5", + transform=ax.transAxes, + verticalalignment="center", + horizontalalignment="left", + ) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy