我正在尝试使用步进增量创建自定义SpinCtrl。看起来这么简单,所以我很惊讶原生的SpinCtrl似乎没有这个功能,谷歌在这件事上也证明是无用的。
然而,当我尝试制作一个自定义的时候,我遇到了问题。这是一些快速而又脏的代码
class SpinStepCtrl( wx.SpinCtrl ):
def __init__( self, *args, **kwargs ):
super( SpinStepCtrl, self ).__init__( *args, **kwargs )
self.step = 99
self.Bind( wx.EVT_SPINCTRL, self.OnSpin )
#self.Bind( wx.EVT_SPIN_UP, self.OnUp )
#self.Bind( wx.EVT_SPIN_DOWN, self.OnDown )
def OnSpin( self, event ):
print 'X'
self.SetValue( self.GetValue() + self.step )
print 就在那里,所以我可以看到发生了什么。 EVT_SPIN_UP和EVT_SPIN_DOWN事件似乎根本不起作用,至少从不调用回调,这就是我把它们拿出来的原因。
使用EVT_SPINCTRL时,会调用回调,但最终会进入无限循环,因为 SetValue 显然会导致调用新的此类事件。它无论如何都没有多大帮助,因为我找不到一种方法来判断它是一个旋转还是旋转事件,所以我不能适当地改变它。
如何让它发挥作用?
答案 0 :(得分:1)
好的,不是最好的,但适用于Ubuntu:
#!/usr/bin/python
import wx
class SpinStepCtrl(wx.SpinCtrl):
def __init__(self, *args, **kwargs):
wx.SpinCtrl.__init__(self, *args, **kwargs)
self.step = 99
self.last_value = 0
self.Bind(wx.EVT_SPINCTRL, self.OnSpin)
def OnSpin(self, event):
delta = self.GetValue() - self.last_value
if delta == 0:
return
elif delta > 0:
self.last_value = self.GetValue() + self.step
else:
self.last_value = self.GetValue() - self.step
self.SetValue(self.last_value)
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = wx.Panel(self)
self.spin = SpinStepCtrl(self.panel, min=0, max=1000)
self.Show()
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
不过,我会认为“self.SetValue”会生成“wx.EVT_SPINCTRL”错误。
答案 1 :(得分:1)
wx.lib.agw有floatspin小部件,它有更多选项。我也将它与SetDigits(0)一起用于整数输入。
import wx
import wx.lib.agw.floatspin as FS
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "FloatSpin Demo")
panel = wx.Panel(self)
floatspin = FS.FloatSpin(panel, -1, pos=(50, 50), min_val=0, max_val=1000,
increment=99, value=0, agwStyle=FS.FS_LEFT)
floatspin.SetDigits(0)
# our normal wxApp-derived class, as usual
app = wx.App(0)
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()
答案 2 :(得分:0)
这对我有用:
import wx
class SpinStepCtrl(wx.SpinCtrl):
def __init__(self, *args, **kwargs):
wx.SpinCtrl.__init__(self, *args, **kwargs)
self.step = 99
self.Bind(wx.EVT_SPIN_UP, self.OnUp)
self.Bind(wx.EVT_SPIN_DOWN, self.OnDown)
def OnUp(self, event):
self.SetValue(self.GetValue() + self.step)
def OnDown(self, event):
self.SetValue(self.GetValue() - self.step)
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = wx.Panel(self)
self.spin = SpinStepCtrl(self.panel, min=0, max=1000)
self.Show()
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
答案 3 :(得分:0)
这是我针对 wxSpinCtrl的解决方案,它从列表中取值进行旋转。 很遗憾,来自wx.SpinButton的事件EVT_SPIN_UP和EVT_SPIN_DOWN不适用于所有平台(不适用于wx 4.0.6和Windows 10/64位)
import wx
class SpinCtrlList(wx.SpinCtrl):
def __init__(self, *args, **kwargs):
wx.SpinCtrl.__init__(self, *args, **kwargs)
self.Bind(wx.EVT_SPINCTRL, self._on_spin)
self.SetList([0, 1])
self.sp_old_value = self.GetValue()
def SetList(self, thelist):
self.thelist = thelist
self.SetRange(self.thelist[0], self.thelist[len(self.thelist)-1])
def GetList(self):
return self.thelist
def _next_greater_ele(self, in_list, in_val):
for x, val in enumerate(in_list):
if val > in_val:
break
return val
def _next_smaller_ele(self, in_list, in_val):
for x, val in enumerate(reversed(in_list)):
if val < in_val:
break
return val
def _on_spin(self, event):
self.sp_new_value = self.GetValue()
if self.sp_new_value > self.sp_old_value:
set_val = self._next_greater_ele(self.thelist, self.sp_new_value)
self.SetValue(set_val)
self.sp_old_value = set_val
elif self.sp_new_value < self.sp_old_value:
set_val = self._next_smaller_ele(self.thelist, self.sp_new_value)
self.SetValue(set_val)
self.sp_old_value = set_val
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = wx.Panel(self)
self.spin = SpinCtrlList(self.panel)
ctrl_list = [100, 200, 500, 1000, 2000, 5000]
self.spin.SetList(ctrl_list)
self.Show()
def main():
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
if __name__ == '__main__':
main()