具有步进增量值的SpinCtrl

时间:2011-03-24 09:40:25

标签: python wxpython

我正在尝试使用步进增量创建自定义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 显然会导致调用新的此类事件。它无论如何都没有多大帮助,因为我找不到一种方法来判断它是一个旋转还是旋转事件,所以我不能适当地改变它。

如何让它发挥作用?

4 个答案:

答案 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()