2010-07-16 7 views
5

wx.SpinCtrl è limitato alla rotazione su interi e non a virgola mobile. Pertanto, sto creando una classe combo wx.TextCtrl + wx.SpinButton che mi consente di ruotare su float. Sono in grado di dimensionare e impaginare entrambi in modo programmatico in modo che la combinazione abbia lo stesso aspetto di un normale wx.SpinCtrl.wxPython: "Super" wx.SpinCtrl con valori float, layout all'interno di sizer

Sto creando una sottoclasse di questa combinazione dallo wx.TextCtrl perché voglio che il suo pannello padre catturi gli eventi wx.EVT_TEXT. Apprezzerei se tu potessi migliorare su questo mio argomento.

Gli eventi wx.EVT_SPIN_UP e wx.EVT_SPIN_DOWN dallo wx.SpinButton sono entrambe implementazioni interne e al frame principale non interessa questi eventi.

Ora, ho appena colpito un muro di mattoni. La mia classe combinata non funziona bene con le calibratrici. Dopo la .Add() della classe combo in un wx.GridBagSizer, solo lo wx.TextCtrl è disposto all'interno dello wx.GridBagSizer. Il wx.SpinButton è lasciato da solo da solo. Le associazioni wx.EVT_SPIN* funzionano molto bene, però.

Il mio problema è il layout. Come dovrei scrivere la classe se voglio che lo wx.GridBagSizer lo consideri come un unico widget?

Ecco il mio combo codice della classe:

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) 

risposta

3

È necessario eseguire l'override DoGetBestSize() se si desidera che il controllo sia correttamente gestito da sizers. Dai un'occhiata a CreatingCustomControls.

Si potrebbe anche dare un'occhiata a FloatSpin fornito con wxPython (in wx.lib.agw) dalla versione 2.8.9.2 verso l'alto.

In risposta ai vostri commenti:

  • Implementazione DoGetBestSize() non richiede disegno direttamente bitmap. Hai solo bisogno di trovare un modo, come è possibile determinare la dimensione migliore del nuovo widget. Solitamente si usa semplicemente le dimensioni dei due widget di cui è composto (testo + spinner) come base.
  • Per consentire ai sizer di trattare due widget come uno, è possibile inserirli in un altro sizer.
  • Il metodo consigliato per implementare un widget personalizzato con wxPython è quello di ricavare il nuovo widget da wx.PyControl, aggiungere un sizer e aggiungere i due widget che si desidera combinare a tale sizer.
+0

Va bene prendo uno sguardo al 'wx.lib.agw.FloatSpin'. Circa l'altro collegamento che mi hai dato (CreatingCustomControls), richiede il disegno di bitmap direttamente, cosa che non sono disposto a fare al momento. Esiste una procedura in wxPython che abilita un sizer a trattare due widget come uno?Dovrebbe essere simile alla funzione di gruppo quando si disegnano molti oggetti in MS Word. – Kit

+0

'FloatSpin' sembra promettente :) Ma questo' wx.PyControl' con un 'wx.Sizer' che contiene il mio' wx.TextCtrl' e 'wx.SpinButton' è davvero interessante. Sto incontrando problemi con '.SetSizer (sizer)' ing il 'wx.PyControl', ma quella sarebbe un'altra domanda. Grazie per il tempo, Ralph! – Kit

1

Come menzionato nei commenti di Kit, FloatSpin è ora la strada da percorrere.

È stato integrato nelle versioni recenti.

Ecco un semplice esempio di utilizzo:

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