开发者

SpinCtrl with step increment value

I'm trying to create a custom SpinCtrl with a step increment. It seems li开发者_StackOverflowke such a simple thing so I was surprised the native SpinCtrl doesn't appear to have this functionality, and Google proves uncommonly useless in this matter as well.

When I try to make a custom one, however, I run into problems. Here's some quick and dirty code

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 )

The print is just there so I can see what, if anything, happens. The EVT_SPIN_UP and EVT_SPIN_DOWN events don't seem to work at all, at least the callbacks are never called which is why I took them out.

When using EVT_SPINCTRL, the callback is called, but end up in an infinite loop because SetValue apparently causes a new such event to be called. It doesn't help much either way, because I can't find a way of telling whether it was a spin up or spin down event, so I can't change the value appropriately.

How do I get this to work?


wx.lib.agw has floatspin widget which has more options. I use it with SetDigits(0) for integer input as well.

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


OK, not the best, but works on 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()

Still, I would consider "self.SetValue" generating "wx.EVT_SPINCTRL" a bug.


This works for me:

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


Here is my solution for wxSpinCtrl, which takes values from a list to spin. It is a pity that the events EVT_SPIN_UP and EVT_SPIN_DOWN from wx.SpinButton do not work under all platforms (not working here with wx 4.0.6 and Windows 10 / 64 Bit)

import wx

class SpinCtrlList(wx.SpinCtrl):
    """A SpinCtrl that spins through a given list. This list must be in
    ascending order and the values of the list must be integers,
    whereat negative numbers are allowed
    """
    def __init__(self, *args, **kwargs):
        wx.SpinCtrl.__init__(self, *args, **kwargs)
        self.Bind(wx.EVT_SPINCTRL, self._on_spin)
        self.thelist = ([0,1])
        self.SetList([0, 1])
        self.SetValue(self.thelist[0])

    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 SetValue(self, val):
        self.sp_old_value = val
        super(SpinCtrlList, self).SetValue(val)

    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()
        #print(self.sp_old_value, self.sp_new_value)
        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, 10000, 12000, 15000]
        #ctrl_list = [-300, -100, 0]
        self.spin.SetList(ctrl_list)
        self.spin.SetValue(ctrl_list[-2])
        self.Show()

def main():
    app = wx.App(False)
    win = MainWindow(None)
    app.MainLoop()

if __name__ == '__main__':
    main()
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜