带步进增量值的旋转控件

2 投票
4 回答
3895 浏览
提问于 2025-04-16 14:19

我正在尝试创建一个自定义的旋转控件(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

这个对我有效:

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

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()
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”算是个bug。

撰写回答