如何将 wx.Slider 与 SELRANGE 一起使用?
how to use wx.Slider with SELRANGE?
在 wx.Slider
(wxPython for py2, wxPython for py3, wxWidgets) 的文档中,列出了一个名为 wx.SL_SELRANGE
的小部件控件,定义为允许 "the user to select a range on the slider (MSW only)"。对我来说,这就是双控制,同一轴上的两个滑块以定义 low/high 范围。我无法让它显示两个控件。
入门的基本代码。在这一点上,我什至不担心方法、事件或诸如此类的东西,只是为了展示一些东西。
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)
尽管如此,我最多只能显示一条蓝线,横跨我期望的位置。
wxPython 文档都在谈论它,但是用户应该如何能够 "select a range on the slider",如此处所示(摘自 shiny
)?
我错过了什么?是否有任何合理的 public 具有此功能的 wxPython wx.Slider
示例?
PS:
- 我找到的一个页面只提到了 WinXP,但由于该页面已经七年没有更新,所以我认为它在版本限制上不具有权威性。
- 我一直在使用 wxGlade 进行 gui 布局,但我肯定 willing/able 在导出后进入代码并四处乱转。
系统:win81_64,python-2.7.10,wxPython-3.0.2.0
我为此做了一个自定义实现,部分使用了来自 this question 的代码。左键单击滑块区域设置范围的左边界,右击设置范围的右边界。拖动滑块移动选择。 left_gap
和 right_gap
表示小部件边缘和绘制滑块的实际开始之间的空白 space 是什么。和源码一样,这些都要通过实验才能发现。
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
我以前遇到过同样的问题,但找不到好的解决方案。我最终做的是用两个实际的拇指创建我自己的自定义 RangeSlider
小部件。
answer, or in this GitHub gist.
中提供了代码
迟到总比不到好:回答最初的问题,wxSL_SELRANGE
确实有效,但只有在与 wxSL_LABELS
结合使用时才会产生预期的效果。使用这两种样式(总范围 0..100 的选择设置为 20..80),控件显示如下:
在 wx.Slider
(wxPython for py2, wxPython for py3, wxWidgets) 的文档中,列出了一个名为 wx.SL_SELRANGE
的小部件控件,定义为允许 "the user to select a range on the slider (MSW only)"。对我来说,这就是双控制,同一轴上的两个滑块以定义 low/high 范围。我无法让它显示两个控件。
入门的基本代码。在这一点上,我什至不担心方法、事件或诸如此类的东西,只是为了展示一些东西。
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)
尽管如此,我最多只能显示一条蓝线,横跨我期望的位置。
wxPython 文档都在谈论它,但是用户应该如何能够 "select a range on the slider",如此处所示(摘自 shiny
)?
我错过了什么?是否有任何合理的 public 具有此功能的 wxPython wx.Slider
示例?
PS:
- 我找到的一个页面只提到了 WinXP,但由于该页面已经七年没有更新,所以我认为它在版本限制上不具有权威性。
- 我一直在使用 wxGlade 进行 gui 布局,但我肯定 willing/able 在导出后进入代码并四处乱转。
系统:win81_64,python-2.7.10,wxPython-3.0.2.0
我为此做了一个自定义实现,部分使用了来自 this question 的代码。左键单击滑块区域设置范围的左边界,右击设置范围的右边界。拖动滑块移动选择。 left_gap
和 right_gap
表示小部件边缘和绘制滑块的实际开始之间的空白 space 是什么。和源码一样,这些都要通过实验才能发现。
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
我以前遇到过同样的问题,但找不到好的解决方案。我最终做的是用两个实际的拇指创建我自己的自定义 RangeSlider
小部件。
answer, or in this GitHub gist.
迟到总比不到好:回答最初的问题,wxSL_SELRANGE
确实有效,但只有在与 wxSL_LABELS
结合使用时才会产生预期的效果。使用这两种样式(总范围 0..100 的选择设置为 20..80),控件显示如下: