Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Improve default formatter for Slider values. #17077

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 1 commit into from
Apr 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/api/api_changes_3.3/behaviour.rst
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,11 @@ support for it will be dropped in a future Matplotlib release.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Previously, keyword arguments were silently ignored when no positional
arguments were given.

Default slider formatter
~~~~~~~~~~~~~~~~~~~~~~~~
The default method used to format `.Slider` values has been changed to use a
`.ScalarFormatter` adapted the slider values limits. This should ensure that
values are displayed with an appropriate number of significant digits even if
they are much smaller or much bigger than 1. To restore the old behavior,
explicitly pass a "%1.2f" as the *valfmt* parameter to `.Slider`.
38 changes: 29 additions & 9 deletions lib/matplotlib/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import numpy as np

import matplotlib as mpl
from . import cbook
from . import cbook, ticker
from .lines import Line2D
from .patches import Circle, Rectangle, Ellipse
from .transforms import blended_transform_factory
Expand Down Expand Up @@ -256,7 +256,8 @@ class Slider(AxesWidget):
val : float
Slider value.
"""
def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',

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', **kwargs):
Expand All @@ -278,8 +279,9 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',
valinit : float, default: 0.5
The slider initial position.

valfmt : str, default: "%1.2f"
Used to format the slider value, fprint format string.
valfmt : str, default: None
%-format string used to format the slider value. If None, a
`.ScalarFormatter` is used instead.

closedmin : bool, default: True
Whether the slider interval is closed on the bottom.
Expand Down Expand Up @@ -347,13 +349,22 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',
self.poly = ax.axvspan(valmin, valinit, 0, 1, **kwargs)
self.vline = ax.axvline(valinit, 0, 1, color='r', lw=1)

self.valfmt = valfmt
ax.set_yticks([])
if orientation == 'vertical':
ax.set_ylim((valmin, valmax))
axis = ax.yaxis
else:
ax.set_xlim((valmin, valmax))
axis = ax.xaxis

self.valfmt = valfmt
self._fmt = axis.get_major_formatter()
Copy link
Member

Choose a reason for hiding this comment

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

Is this attribute is introduced here? If so, let's call it

Suggested change
self._fmt = axis.get_major_formatter()
self._formatter = axis.get_major_formatter()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fmt for format(ter) is a pretty standard abbreviation, and this avoids an awkward linebreak a bit later which also helps from a legibility PoV. OTOH I don't really want to argue too much over this so if you are sure you prefer _formatter, let me know and I'll do the change (yes, it's a new attribute, so we can call it however we want).

Copy link
Member

Choose a reason for hiding this comment

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

If I see fmt I expand to format in my mind, but I do not expand to formatter. OTOH, this isn't really a big deal here.

if not isinstance(self._fmt, ticker.ScalarFormatter):
self._fmt = ticker.ScalarFormatter()
self._fmt.set_axis(axis)
self._fmt.set_useOffset(False) # No additive offset.

ax.set_xticks([])
ax.set_yticks([])
ax.set_navigate(False)

self.connect_event('button_press_event', self._update)
Expand All @@ -365,7 +376,7 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',
verticalalignment='bottom',
horizontalalignment='center')

self.valtext = ax.text(0.5, -0.02, valfmt % valinit,
self.valtext = ax.text(0.5, -0.02, self._format(valinit),
transform=ax.transAxes,
verticalalignment='top',
horizontalalignment='center')
Expand All @@ -374,7 +385,7 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',
verticalalignment='center',
horizontalalignment='right')

self.valtext = ax.text(1.02, 0.5, valfmt % valinit,
self.valtext = ax.text(1.02, 0.5, self._format(valinit),
transform=ax.transAxes,
verticalalignment='center',
horizontalalignment='left')
Expand Down Expand Up @@ -435,6 +446,15 @@ def _update(self, event):
if val not in [None, self.val]:
self.set_val(val)

def _format(self, val):
"""Pretty-print *val*."""
if self.valfmt is not None:
return self.valfmt % val
else:
_, s, _ = self._fmt.format_ticks([self.valmin, val, self.valmax])
# fmt.get_offset is actually the multiplicative factor, if any.
return s + self._fmt.get_offset()

Choose a reason for hiding this comment

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

This will result in 3e-8 to be shown as 31e-8.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oops, I had axes.formatter.usemathtext in my rcdefaults, we just need to force that here...


def set_val(self, val):
"""
Set slider value to *val*
Expand All @@ -451,7 +471,7 @@ def set_val(self, val):
xy[2] = val, 1
xy[3] = val, 0
self.poly.xy = xy
self.valtext.set_text(self.valfmt % val)
self.valtext.set_text(self._format(val))
if self.drawon:
self.ax.figure.canvas.draw_idle()
self.val = val
Expand Down