-
Notifications
You must be signed in to change notification settings - Fork 2
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 anotherT
(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 aT
into a number -
value_from_number(x)
to convert a number into aT
-
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)