WxPython: "Super" wx.SpinCtrl with float values, layout inside sizer

wx.SpinCtrllimited to spinning integers, not floating. Therefore, I create a combo class wx.TextCtrl+ wx.SpinButtonthat allows me to rotate on floats. I can size and position both programmatically, so the combo looks exactly the same as normal wx.SpinCtrl.

I will subclass this combo from wx.TextCtrlbecause I want its parent panel to catch events wx.EVT_TEXT. I would appreciate it if you could improve this argument.

Events in wx.EVT_SPIN_UPand wx.EVT_SPIN_DOWNout wx.SpinButtonare internal implementations, and the parent frame does not care about these events.

Now I just hit a brick wall. My combo class does not work with sizers. After the .Add()combo class, c wx.GridBagSizeris wx.GridBagSizerlaid out only wx.TextCtrl. wx.SpinButtonstays on its own. However, bindings wx.EVT_SPIN*work very well.

My problem is the layout. How to write a class if I want to wx.GridBagSizerconsider it as one widget?

Here is my combo class code:

class SpinnerSuper(wx.TextCtrl):
  def __init__(self, parent, max):
    wx.TextCtrl.__init__(self, parent=parent, size=(48, -1))
    spin = wx.SpinButton(parent=parent, style=wx.SP_VERTICAL, size=(-1, 21))
    self.OnInit()
    self.layout(spin)
    self.internalBindings(spin)
    self.SizerFlag = wx.ALIGN_CENTER

    self.min = 0
    self.max = max

  def OnInit(self):
    self.SetValue(u"0.000")

  def layout(self, spin):
    pos = self.GetPosition()
    size = self.GetSize()
    RightEdge = pos[0] + size[0]
    TopEdge = pos[1] - (spin.GetSize()[1]/2 - size[1]/2)
    spin.SetPosition((RightEdge, TopEdge))

  def internalBindings(self, spin):
    spin.Bind(wx.EVT_SPIN_UP, self.handlerSpinUp(self), spin)
    spin.Bind(wx.EVT_SPIN_DOWN, self.handlerSpinDown(self), spin)

  def handlerSpinUp(CallerObject, *args):
    def handler(CallerObject, *data):
        text = data[0]
        prev = text.GetValue()
        next = float(prev) + 0.008
        text.SetValue("{0:0.3f}".format(next))
    return lambda event: handler(CallerObject, *args)

  def handlerSpinDown(CallerObject, *args):
    def handler(CallerObject, *data):
        text = data[0]
        prev = text.GetValue()
        next = float(prev) - 0.008
        text.SetValue("{0:0.3f}".format(next))
    return lambda event: handler(CallerObject, *args)
+5
source share
2 answers

You need to override DoGetBestSize () if you want your control to be properly managed by sizers. Take a look at CreatingCustomControls .

FloatSpin, wxPython ( wx.lib.agw) 2.8.9.2 .

:

  • DoGetBestSize() . , . (text + spinner) .
  • sizers , sizer.
  • wxPython , wx.PyControl, sizer , sizer.
+3

Kit, FloatSpin .

.

:

import wx
from wx.lib.agw.floatspin import FloatSpin

class Example_FloatSpin(wx.Frame):
    def __init__(self, parent, title):
        super(Example_FloatSpin, self).__init__(parent, title=title, size=(480, 250))
        panel = wx.Panel(self)

        vbox = wx.BoxSizer(wx.VERTICAL)
        spin = FloatSpin(panel, value=0.0, min_val=0.0, max_val=8.0, increment=0.5, digits=2, size=(100,-1))
        vbox.Add(spin, proportion=0, flag=wx.CENTER, border=15)
        panel.SetSizer(vbox)

        self.Centre()
        self.Show() 


if __name__ == '__main__':
    app = wx.App()
    Example_FloatSpin(None, title='Check FloatSpin')
    app.MainLoop()
+1

All Articles