2010-07-16 15 views
5

wx.SpinCtrl está limitado a girar a través de enteros, y no flota. Por lo tanto, estoy construyendo una clase wx.TextCtrl + wx.SpinButton combo que me permite girar a través de flotadores. Puedo ajustar el tamaño y el diseño de ambos de manera programática para que el combo se vea exactamente igual a un wx.SpinCtrl normal.wxPython: "Super" wx.SpinCtrl con valores flotantes, diseño dentro del medidor

Estoy subclasiendo este combo del wx.TextCtrl porque quiero que su panel principal capte los eventos wx.EVT_TEXT. Agradecería si puedes mejorar este argumento mío.

Los wx.EVT_SPIN_UP y wx.EVT_SPIN_DOWN eventos del wx.SpinButton son ambas implementaciones internas y el marco de los padres no se preocupan por estos eventos.

Ahora, me acabo de pegar en una pared de ladrillos. Mi clase de combo no funciona bien con los sizers. Después de .Add() ing la clase combinada a wx.GridBagSizer, solo el wx.TextCtrl se presenta dentro del wx.GridBagSizer. El wx.SpinButton se deja solo. Sin embargo, las vinculaciones wx.EVT_SPIN* funcionan muy bien.

Mi problema es el diseño. ¿Cómo debo escribir la clase si quiero que el wx.GridBagSizer lo trate como un widget?

Aquí es mi combo código de clase:

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) 

Respuesta

3

Necesita anular DoGetBestSize() si desea que su control sea administrado correctamente por medidores. Eche un vistazo al CreatingCustomControls.

También puede consultar FloatSpin que se envía con wxPython (en wx.lib.agw) desde la versión 2.8.9.2 en adelante.

En respuesta a sus comentarios:

  • Ejecución DoGetBestSize() no requiere de la elaboración de mapas de bits directamente. Solo necesita encontrar la manera, cómo puede determinar el mejor tamaño de su nuevo widget. Normalmente, utilizará los tamaños de los dos widgets de los que está compuesto (texto + ruleta) como base.
  • para permitir que tratan medidores dos widgets como una sola, puede colocarlos en otro medidor.
  • La forma recomendada de implementar un widget personalizado con wxPython es derivar su nuevo widget de wx.PyControl, agregarle un sizer y agregar los dos widgets que desea combinar con ese sizer.
+0

bien voy a echar un vistazo a 'wx.lib.agw.FloatSpin'. Sobre el otro enlace que me diste (CreatingCustomControls), se requiere la elaboración de mapas de bits directamente, lo que no estoy dispuesto a hacer por el momento. ¿Hay algún procedimiento en wxPython que permita que un medidor trate dos widgets como uno solo?Debería ser similar a la función de grupo al dibujar muchos objetos en MS Word. – Kit

+0

'FloatSpin' parece prometedor :) Pero este' wx.PyControl' con un 'wx.Sizer' que contiene mi' wx.TextCtrl' y 'wx.SpinButton' es realmente interesante. Estoy teniendo problemas con '.SetSizer (sizer)' ing the 'wx.PyControl', pero esa sería otra pregunta. Gracias por el tiempo, Ralph! – Kit

1

Como mencionamos en los comentarios de Kit, FloatSpin es ahora el camino a seguir.

Se ha integrado en las versiones recientes.

Aquí es un simple ejemplo de uso:

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