3

I want to choose a point of a triangle by choosing its weights. This should be done by controlling 2 Sliders (matplotlib.widgets.Slider). These two sliders express two out of three weights that define the point. The third weight is easily calculated as 1.0 - slider1 - slider2.

Now it is clear that the sum of all weights should be equal to 1.0, so choosing 0.8 and 0.9 as the values for the two sliders should be impossible. The argument slidermax allows to make sliders dependent, but I can not say:

slider2 = Slider(... , slidermax = 1.0-slider1)

slidermax requires a type Slider, not integer. How can I create dependencies a little more complex than this slidermax option?

tshepang
  • 12,111
  • 21
  • 91
  • 136
Jan
  • 111
  • 2
  • 7
  • Can you reformat this so it is more readable? Do you want to do this with matplotlib's gui independent widgets, or in some specific tool kit? – tacaswell Dec 23 '13 at 21:16
  • I want to do it without external packages, since the Sliders work well (except for their constraints so far) – Jan Dec 23 '13 at 21:51
  • 1
    Obviously this is cheating, but maybe it would be easier to make `slider2` represent the fraction (always between 0 and 1) of the remainder `1-slider1`. That way, `slider1` and `slider2` can range between 0 and 1 independently. Thus, if `w1`, `w2` and `w3` are the 3 weights, then `w1 = slider1`, `w2 = slider2*(1-w1)`, and `w3 = 1 - w1 - w2`. – unutbu Dec 24 '13 at 00:44

1 Answers1

2

@ubuntu's answer is the simple way.

Another option is to subclass Slider to do exactly what you want. This would be the most flexible (and you could even make the sliders update each other, which they currently don't do).

However, it's easy to use "ducktyping" in this case. The only requirement is that slidermin and slidermax have a val attribute. They don't actually have to be instances of Slider.

With that in mind, you could do something like:

import matplotlib.pyplot as plt
from matplotlib.widgets import Slider

class FakeSlider(object):
    def __init__(self, slider, func):
        self.func, self.slider = func, slider
    @property
    def val(self):
        return self.func(self.slider.val)

fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.25)

sliderax1 = fig.add_axes([0.15, 0.1, 0.75, 0.03], axisbg='gray')
sliderax2  = fig.add_axes([0.15, 0.15, 0.75, 0.03], axisbg='gray')

slider1 = Slider(sliderax1, 'Value 1', 0.1, 5, valinit=2)
slider2 = Slider(sliderax2, 'Value 2', -4, 0.9, valinit=-3,
                 slidermax=FakeSlider(slider1, lambda x: 1 - x))
plt.show()
Joe Kington
  • 275,208
  • 71
  • 604
  • 463