In the docs for wx.Slider
(wxPython for py2, wxPython for py3, wxWidgets), there is listed a widget control named wx.SL_SELRANGE
, defined to allow "the user to select a range on the slider (MSW only)". To me, this speaks of a twin-control, two sliders on the same axis in order to define a low/high range. I can't get it to show two controls.
Basic code to get it started. I'm not even worried yet about methods, events, or whatnot at this point, just to show something.
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
# ... sizers and other stuff
self.myslider = wx.Slider(self.notebook_1_pane_2, wx.ID_ANY, 0, -100, 100, style=wx.SL_SELRANGE)
# ...
self.myslider.SetSelection(10, 90)
With all of that, the most I've been able to get it to show is a blue line spanning about where I would expect things to be.
The wxPython docs all talk about it but how is the user supposed to be able to "select a range on the slider", like shown here (taken from shiny
)?
What am I missing? Are there any reasonable public examples of a wxPython wx.Slider
in the wild with this functionality?
PS:
System: win81_64, python-2.7.10, wxPython-3.0.2.0
I have made a custom implementation for this, partly using a code from this question. Left click on the slider area sets the left border of the range, right click sets the right border. Dragging the slider moves the selection. left_gap
and right_gap
indicates what is the empty space between edges of the widget and actual start of the drawn slider. As in the source, these must be found out by experimentation.
class RangeSlider(wx.Slider):
def __init__(self, left_gap, right_gap, *args, **kwargs):
wx.Slider.__init__(self, *args, **kwargs)
self.left_gap = left_gap
self.right_gap = right_gap
self.Bind(wx.EVT_LEFT_UP, self.on_left_click)
self.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
self.Bind(wx.EVT_SCROLL_PAGEUP, self.on_pageup)
self.Bind(wx.EVT_SCROLL_PAGEDOWN, self.on_pagedown)
self.Bind(wx.EVT_SCROLL_THUMBTRACK, self.on_slide)
self.slider_value=self.Value
self.is_dragging=False
def linapp(self, x1, x2, y1, y2, x):
proportion=float(x - x1) / (x2 - x1)
length = y2 - y1
return round(proportion*length + y1)
# if left click set the start of selection
def on_left_click(self, e):
if not self.is_dragging: #if this wasn't a dragging operation
position = self.get_position(e)
if position <= self.SelEnd:
self.SetSelection(position, self.SelEnd)
else:
self.SetSelection(self.SelEnd, position)
else:
self.is_dragging = False
e.Skip()
# if right click set the end of selection
def on_right_click(self, e):
position = self.get_position(e)
if position >= self.SelStart:
self.SetSelection(self.SelStart, position)
else:
self.SetSelection(position, self.SelStart)
e.Skip()
# drag the selection along when sliding
def on_slide(self, e):
self.is_dragging=True
delta_distance=self.Value-self.slider_value
self.SetSelection(self.SelStart+delta_distance, self.SelEnd+delta_distance)
self.slider_value=self.Value
# disable pageup and pagedown using following functions
def on_pageup(self, e):
self.SetValue(self.Value+self.PageSize)
def on_pagedown(self, e):
self.SetValue(self.Value-self.PageSize)
# get click position on the slider scale
def get_position(self, e):
click_min = self.left_gap #standard size 9
click_max = self.GetSize()[0] - self.right_gap #standard size 55
click_position = e.GetX()
result_min = self.GetMin()
result_max = self.GetMax()
if click_position > click_min and click_position < click_max:
result = self.linapp(click_min, click_max,
result_min, result_max,
click_position)
elif click_position <= click_min:
result = result_min
else:
result = result_max
return result
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With