Skip to content

Make Your Own Sliders

speezepearson edited this page Nov 22, 2015 · 1 revision

Maybe you want to present your user with a slider to input a date in a particular range. You could use an IntegerSlider, and add slider.value * one_day to some base date every time you retrieve the value... but it would be more elegant to write your own DateSlider class which takes care of all the conversion for you.

Luckily, this is easy! And it's easy for any exotic data type T you like, as long as:

  • you can convert a T into a number (to turn a value into a slider-position)
  • you can convert a number into a T (to turn a slider-position into a value)
  • you can compare a T to another T (to make sure a value is between the slider's min and max)

You just declare your own subclass of Slider, and define:

  • value_to_number(x) to convert a T into a number
  • value_from_number(x) to convert a number into a T
  • DISCRETE to indicate whether the user should be able to move the slider wherever they want (useful for continuous data types like datetimes), or only to evenly-spaced points (useful for discrete data types like datetimes).

A couple examples:

_TIMEDELTA_ZERO = datetime.timedelta(0)
class TimedeltaSlider(Slider):
  DISCRETE = False

  @staticmethod
  def value_to_number(x):
    if not isinstance(x, datetime.timedelta):
      raise TypeError('expected timedelta, got {}'.format(type(x).__name__))
    return x.total_seconds()

  @staticmethod
  def value_from_number(x):
    return datetime.timedelta(seconds=x)

_DATE_ZERO = datetime.date(2015, 1, 1)
class DateSlider(Slider):
  DISCRETE = True

  @staticmethod
  def value_to_number(x):
    if not isinstance(x, datetime.date):
      raise TypeError('expected date, got {}'.format(type(x).__name__))
    return int(round((x-_DATE_ZERO).total_seconds() / datetime.timedelta(days=1).total_seconds()))

  @staticmethod
  def value_from_number(x):
    return _DATE_ZERO + datetime.timedelta(days=x)
Clone this wiki locally