[wxPython] missing wxSpinEvents

I am trying to derive a class from wxTextCtrl that can, after
instantiation, have a wxSpinButton bound to it. I need to do this
because I can't access the underlying wxTextCtrl of a wxSpinCtrl,
and I want a spin button associated with the text control that changes
different parts of the text based on the insertion point.

So I am trying to "roll my own..." However, I can't seem to get the
wxSpinButton's events to fire my handler.

Below is a complete (though trivial) program that illustrates the
problem.

Could someone explain why the OnSpinChange method never fires?
Is there a way to fix this?

(wxPython 2.3.2.1, Python 2.1, MSW)

Thanks in advance,
/Will Sadkin

···

#-------------------------------------------------------------------------

from wxPython.wx import *

class wxMyCtrl(wxTextCtrl):
    def __init__ (
        self, parent, id=-1, value="", pos=wxDefaultPosition,
size=wxDefaultSize,
        spinButton = None,
        style = wxTE_PROCESS_TAB, name = "myctrl"):

        wxTextCtrl.__init__(self, parent, id, value=value,
                            pos=pos, size=size, style=style, name=name)

        self.SetSpinButton(spinButton)
        EVT_TEXT(self, self.GetId(), self.OnTextChange)

    def SetSpinButton(self, spinButton):
        self.m_spinButton = spinButton
        if self.m_spinButton:
            EVT_SPIN(self, self.m_spinButton.GetId(), self.OnSpinChange)

    def OnSpinChange(self, event):
### THESE DON'T FIRE...
        print 'OnSpinChange', self.m_spinButton.GetValue()
        self.SetValue(str(self.m_spinButton.GetValue()))
    
    def OnTextChange(self, event):
        print 'OnTextChange', self.GetValue()

class TestPanel(wxPanel):
    def __init__(self, parent, id,
        pos = wxPyDefaultPosition, size = wxPyDefaultSize, style =
wxTAB_TRAVERSAL ):

        wxPanel.__init__(self, parent, id, pos, size, style)
        sizer = wxBoxSizer( wxHORIZONTAL )
    
        mytc = wxMyCtrl(self, 10, "custom control", size = wxSize(80,-1) )
        sizer.AddWindow( mytc, 0, wxALIGN_CENTRE|wxLEFT|wxTOP|wxBOTTOM, 5 )

        sb = wxSpinButton(self, 20, wxDefaultPosition, wxSize(-1,20), 0 )
        sb.SetRange( 0, 100 )
        sb.SetValue( 0 )
        sizer.AddWindow( sb, 0, wxALIGN_CENTRE|wxRIGHT|wxTOP|wxBOTTOM, 5 )

        self.SetAutoLayout( true )
        self.SetSizer( sizer )
        sizer.Fit( self )
        sizer.SetSizeHints( self )

        # associate spin button with derived control
        mytc.SetSpinButton(sb)

#-------------------------------------------------------------------------

import traceback

class MyApp(wxApp):
    
    def OnInit(self):
        try:
            frame = wxFrame(NULL, -1, "Junk", wxPoint(20,20),
wxSize(500,180) )
            panel = TestPanel(frame, -1, wxPoint(-1,-1))
            frame.Show(true)
        except:
            traceback.print_exc()
            return false
        
        return true
    
if __name__ == '__main__':
    try:
        app = MyApp(0)
        app.MainLoop()
    except:
        traceback.print_exc()

Could someone explain why the OnSpinChange method never fires?
Is there a way to fix this?

The spin button is a child of the panel, but you are attaching the event
handler to the text control. The event won't get there because the spin
button passes it up to the panel which passes it up to...

You can also catch the event in the spin button itself if you like. This
single change will fix your sample:

EVT_SPIN(self.m_spinButton, self.m_spinButton.GetId(), self.OnSpinChange)

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!