Unexpected wxPyDeadObjectError

Hi,
  I'm making some validators for the program I'm working on and got stuck
with this one.
  The problem is that when RangeValidator is instanciated I get a
wxPyDeadObjectError exception. I never got anything like this before and
don't know how to avoid it but everything seems to work correctly anyway.
  I'm using Python 2.2.2 and wxPython 2.4.0.3 on Win2000.

TIA,
  Javier

PS: I never used wxCallAfter before either and found nothing in the docs
for it so I was also wondering if I'm using it correctly.

--- Exception --------------------------------------------------

Traceback (most recent call last):
  File "C:\Python22\lib\site-packages\wxPython\wx.py", line 1645, in
<lambda>
    lambda event: apply(event.callable, event.args, event.kw) )
  File "paquetes\stock\mantenimiento\producto.py", line 528, in __call__
    ctrl = self.validator.GetWindow()
  File "C:\Python22\lib\site-packages\wxPython\wx.py", line 1678, in
__getattr__
    raise wxPyDeadObjectError( self.attrStr % self._name )
wxPython.wx.wxPyDeadObjectError: The C++ part of the RangeValidator
object has been deleted, attribute access no longer allowed.

···

-----------------------------------------------------------------

--- Code --------------------------------------------------------

# This class only allows allows digits to be entered and if the
# value is invalid, sets the foreground color to 'color_mal'.
class RangeValidator(wxPyValidator):
    """RangeValidator(min=0, max=None, extras=None, color_bien=wxBLACK,
            color_mal=wxRED) -> wxPyValidator

    Este validator se especializa en rangos de números y permite filtrar
    y avisar gráficamente si se está fuera de el rango dado y no en los
    extras o en el rango y en los extras.
    Si el valor del control que se está validando no se encuentra entre
    el rango dado, el texto de este se pone rojo.
    """
    def __init__(self, min=0, max=None, extras=None, color_bien=wxBLACK,
            color_mal=wxRED):
        wxPyValidator.__init__(self)

        self.min = 0
        self.max = max
        self.color_bien = color_bien
        self.color_mal = color_mal
        if extras is None:
            extras = []
        self.extras = extras

        import string
        self.digits = string.digits

        class aux:
            def __init__(self, validator):
                self.validator = validator
            def __call__(self):
                ctrl = self.validator.GetWindow()
                EVT_TEXT(ctrl, ctrl.GetId(), self.validator.OnText)

        wxCallAfter(aux(self))
        EVT_CHAR(self, self.OnChar)

    def Clone(self):
        return RangeValidator(self.min, self.max, self.extras,
self.color_bien, self.color_mal)

    def SetError(self, error):
        if error:
            newColor = self.color_mal
        else:
            newColor = self.color_bien

        ctrl = self.GetWindow()
        if newColor != ctrl.GetForegroundColour():
            ctrl.SetForegroundColour(newColor)
            ctrl.Refresh(False)

    def OnChar(self, event):
        key = event.KeyCode()
        if key < WXK_SPACE or key == WXK_DELETE or key > 255 or \
                chr(key) in self.digits:
            event.Skip()
        elif not wxValidator_IsSilent():
            wxBell()

    def OnText(self, event):
        event.Skip()
        print "OnText", dir(event)
        t = event.GetEventObject().GetValue()
        try:
            n = long(t)
        except ValueError, e:
            self.SetError(t.strip() != '')
            return

        min = self.min
        max = self.max
        ex = self.extras
        error = not ((min <= n and (max is None or n <= max) and n not
in ex) \
                or ((min > n or max is not None and n > max) and n in ex))
        self.SetError(error)

Javier Ruere <javier@uol.com.ar> writes:

PS: I never used wxCallAfter before either and found nothing in the docs
for it so I was also wondering if I'm using it correctly.

def CallAfter(callable, *args, **kw):
    """Call the specified function after the current and pending event
    handlers have been completed. This is also good for making GUI
    method calls from non-GUI threads."""

···

--
Patrick K. O'Brien
Orbtech http://www.orbtech.com/web/pobrien
-----------------------------------------------
"Your source for Python programming expertise."
-----------------------------------------------

I did see the __doc__ but found nothing else.
I don't see the problem yet, sorry.

Patrick K. O'Brien wrote:

···

Javier Ruere <javier@uol.com.ar> writes:

PS: I never used wxCallAfter before either and found nothing in the docs
for it so I was also wondering if I'm using it correctly.

def CallAfter(callable, *args, **kw):
    """Call the specified function after the current and pending event
    handlers have been completed. This is also good for making GUI
    method calls from non-GUI threads."""

By the problem I mean why the exception is raised.

Javier Ruere wrote:

···

I did see the __doc__ but found nothing else.
I don't see the problem yet, sorry.

Patrick K. O'Brien wrote:

Javier Ruere <javier@uol.com.ar> writes:

PS: I never used wxCallAfter before either and found nothing in the docs
for it so I was also wondering if I'm using it correctly.

def CallAfter(callable, *args, **kw):
   """Call the specified function after the current and pending event
   handlers have been completed. This is also good for making GUI
   method calls from non-GUI threads."""

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org

wxPyDeadObjectError is a last-ditch effort to save you from a C++ level memory-access fault (which would crash your application without any useful indication of why).

           def __call__(self):
               ctrl = self.validator.GetWindow()
               EVT_TEXT(ctrl, ctrl.GetId(), self.validator.OnText)

Apparently, at least once in your application, self.validator has already been destroyed by the time wxCallAfter gets around to calling your "aux" instance. The problem is most likely showing up during the destruction of the dialog.

I'm a little surprised by the error showing up so late, given that your aux is created on Validator *initialisation*, which would almost suggest that a new Validator instance is being created at the moment where "Validate()" is happening for the dialog.

[ What I can imagine happening is that the Validator is created on dialog initialisation, then wxCallAfter adds your "aux" object's call-after to the general application event queue, but the *modal* dialog's event-queue pump (a sort of micro-mainloop seperate from the application's) is started _before_ the call-after runs. That would prevent the call-after from running while the dialog is open, then, when it's closed, the call-after is able to run, but everything it refers to has already been cleaned up. ]

You can merely avoid the error with something like this:

    if self.validator: # validator is still alive
        ctrl = self.validator.GetWindow()
        if ctrl: #control is still alive
            EVT_TEXT(ctrl, ctrl.GetId(), self.validator.OnText)

I'm not actually sure _why_ you *want* to use wxCallAfter for binding an event, but I'm assuming you've got a reason, and this should avoid the error, though you then need to be aware that the validator likely will not run properly (see hunch above).

You could try to debug the application by altering wxPyDeadObject in wx.py to do a pdb debugging session instead of raising an error on __getattr__. I suspect you'll just find that every object associated with the dialog has been cleaned up already.

Good luck,
Mike

Javier Ruere wrote:

···

Hi,
I'm making some validators for the program I'm working on and got stuck
with this one.
The problem is that when RangeValidator is instanciated I get a
wxPyDeadObjectError exception. I never got anything like this before and
don't know how to avoid it but everything seems to work correctly anyway.
I'm using Python 2.2.2 and wxPython 2.4.0.3 on Win2000.

TIA,
Javier

PS: I never used wxCallAfter before either and found nothing in the docs
for it so I was also wondering if I'm using it correctly.

--- Exception --------------------------------------------------

Traceback (most recent call last):
File "C:\Python22\lib\site-packages\wxPython\wx.py", line 1645, in
<lambda>
   lambda event: apply(event.callable, event.args, event.kw) )
File "paquetes\stock\mantenimiento\producto.py", line 528, in __call__
   ctrl = self.validator.GetWindow()
File "C:\Python22\lib\site-packages\wxPython\wx.py", line 1678, in
__getattr__
   raise wxPyDeadObjectError( self.attrStr % self._name )
wxPython.wx.wxPyDeadObjectError: The C++ part of the RangeValidator
object has been deleted, attribute access no longer allowed.

-----------------------------------------------------------------

--- Code --------------------------------------------------------

# This class only allows allows digits to be entered and if the
# value is invalid, sets the foreground color to 'color_mal'.
class RangeValidator(wxPyValidator):
   """RangeValidator(min=0, max=None, extras=None, color_bien=wxBLACK,
           color_mal=wxRED) -> wxPyValidator

   Este validator se especializa en rangos de números y permite filtrar
   y avisar gráficamente si se está fuera de el rango dado y no en los
   extras o en el rango y en los extras.
   Si el valor del control que se está validando no se encuentra entre
   el rango dado, el texto de este se pone rojo.
   """
   def __init__(self, min=0, max=None, extras=None, color_bien=wxBLACK,
           color_mal=wxRED):
       wxPyValidator.__init__(self)

       self.min = 0
       self.max = max
       self.color_bien = color_bien
       self.color_mal = color_mal
       if extras is None:
           extras =
       self.extras = extras

       import string
       self.digits = string.digits

       class aux:
           def __init__(self, validator):
               self.validator = validator
           def __call__(self):
               ctrl = self.validator.GetWindow()
               EVT_TEXT(ctrl, ctrl.GetId(), self.validator.OnText)

       wxCallAfter(aux(self))
       EVT_CHAR(self, self.OnChar)

   def Clone(self):
       return RangeValidator(self.min, self.max, self.extras,
self.color_bien, self.color_mal)

   def SetError(self, error):
       if error:
           newColor = self.color_mal
       else:
           newColor = self.color_bien

       ctrl = self.GetWindow()
       if newColor != ctrl.GetForegroundColour():
           ctrl.SetForegroundColour(newColor)
           ctrl.Refresh(False)

   def OnChar(self, event):
       key = event.KeyCode()
       if key < WXK_SPACE or key == WXK_DELETE or key > 255 or \
               chr(key) in self.digits:
           event.Skip()
       elif not wxValidator_IsSilent():
           wxBell()

   def OnText(self, event):
       event.Skip()
       print "OnText", dir(event)
       t = event.GetEventObject().GetValue()
       try:
           n = long(t)
       except ValueError, e:
           self.SetError(t.strip() != '')
           return

       min = self.min
       max = self.max
       ex = self.extras
       error = not ((min <= n and (max is None or n <= max) and n not
in ex) \
               or ((min > n or max is not None and n > max) and n in ex))
       self.SetError(error)

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org

--
_______________________________________
  Mike C. Fletcher
  Designer, VR Plumber, Coder
  http://members.rogers.com/mcfletch/

Mike,

wxPyDeadObjectError is a last-ditch effort to save you from a C++ level
memory-access fault (which would crash your application without any
useful indication of why).

Great!

           def __call__(self):
               ctrl = self.validator.GetWindow()
               EVT_TEXT(ctrl, ctrl.GetId(), self.validator.OnText)

Apparently, at least once in your application, self.validator has
already been destroyed by the time wxCallAfter gets around to calling
your "aux" instance.

This happens every time a validator is created.

The problem is most likely showing up during the
destruction of the dialog.

This happens as soon as the window is created.

[ What I can imagine happening is that the Validator is created on
dialog initialisation, then wxCallAfter adds your "aux" object's
call-after to the general application event queue, but the *modal*
dialog's event-queue pump (a sort of micro-mainloop seperate from the
application's) is started _before_ the call-after runs. That would
prevent the call-after from running while the dialog is open, then, when
it's closed, the call-after is able to run, but everything it refers to
has already been cleaned up. ]

Actually, I'm using this validator in a wxFrame and it does work, even
after throwing an error.

You can merely avoid the error with something like this:

   if self.validator: # validator is still alive
       ctrl = self.validator.GetWindow()
       if ctrl: #control is still alive
           EVT_TEXT(ctrl, ctrl.GetId(), self.validator.OnText)

I didn't know this could be done!!
Thanks a lot, I learned something new!!
Now it works correctly and cause no exception, thank a lot.

I'm not actually sure _why_ you *want* to use wxCallAfter for binding an
event, but I'm assuming you've got a reason, and this should avoid the
error, though you then need to be aware that the validator likely will
not run properly (see hunch above).

Well, using "ctrl = self.GetWindow()" directly in __init__ returns None
so I thought that the validator wasn't completely initialized until it
left the function and the object (a wxTextCtrl in this case) it is
validating asociated (or what ever it does) itself with the validator so
then GetWindow could tell me which object it is validating.
If calling wxCallAfter could be avoided there must be something big I'm
missing and would be happy to be corrected.

You could try to debug the application by altering wxPyDeadObject in
wx.py to do a pdb debugging session instead of raising an error on
__getattr__. I suspect you'll just find that every object associated
with the dialog has been cleaned up already.

I believe you are right but I don't know how to write this correctly.
I need to catch EVT_TEXT but for that I need the control which will be
causing the event so I don't see other way of doing this that what I'm
doing now (with the "if self.validator:" correction).

Thank you very much,
      Javier

Javier Ruere wrote:
...

I'm not actually sure _why_ you *want* to use wxCallAfter for binding an
event, but I'm assuming you've got a reason, and this should avoid the
error, though you then need to be aware that the validator likely will
not run properly (see hunch above).
   
Well, using "ctrl = self.GetWindow()" directly in __init__ returns None
so I thought that the validator wasn't completely initialized until it
left the function and the object (a wxTextCtrl in this case) it is
validating asociated (or what ever it does) itself with the validator so
then GetWindow could tell me which object it is validating.
If calling wxCallAfter could be avoided there must be something big I'm
missing and would be happy to be corrected.

Override SetWindow and do the event binding there. Reading that docs that seems like the correct spot to do the work. It also allows for re-binding the validator to another control.

I believe you are right but I don't know how to write this correctly.
I need to catch EVT_TEXT but for that I need the control which will be
causing the event so I don't see other way of doing this that what I'm
doing now (with the "if self.validator:" correction).

Giving your stated usage patterns, and the symptoms, I'm wondering if possibly the system is doing a Clone() of the first validator you create to store a copy of the validator rather than the original, which would cause the first validator to be garbage-collected before its "aux" object is called. You could check this by using simple print statements to print the id of the validator during the initialization method, and during the aux's call method. If you see something like (for a single "logical" validator creation):

    init 12345
    init 23456
    call 12345
    error
    call 23456
    no error

then this might be the problem.

Enjoy,
Mike

···

_______________________________________
  Mike C. Fletcher
  Designer, VR Plumber, Coder
  http://members.rogers.com/mcfletch/

Mike C. Fletcher wrote:

Giving your stated usage patterns, and the symptoms, I'm wondering if possibly the system is doing a Clone() of the first validator you create to store a copy of the validator rather than the original, which would cause the first validator to be garbage-collected before its "aux" object is called.

Yes. Validators are cloned internal to wxWindows.

···

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

Javier Ruere wrote:

I believe you are right but I don't know how to write this correctly.
I need to catch EVT_TEXT but for that I need the control which will be
causing the event

No you don't. If a window has a validator then it gets all the events first. Just bind the EVT_TEXT to the validator itself.

···

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

Mike C. Fletcher wrote:

Well, using "ctrl = self.GetWindow()" directly in __init__ returns None
so I thought that the validator wasn't completely initialized until it
left the function and the object (a wxTextCtrl in this case) it is
validating asociated (or what ever it does) itself with the validator so
then GetWindow could tell me which object it is validating.
If calling wxCallAfter could be avoided there must be something big I'm
missing and would be happy to be corrected.

Override SetWindow and do the event binding there. Reading that docs
that seems like the correct spot to do the work. It also allows for
re-binding the validator to another control.

This sounds correct but I tried it and noticed that this method is not
being called (at least the one I wrote). I used the following code:

    def SetWindow(self, window):
        print "Associating window!"
        wxPyValidator.SetWindow(self, window)
        EVT_TEXT(window, window.GetId(), self.OnText)

Doing the event binding this way make me wonder if cloned validators are
re-associated or if they are expected to remember the previous
association (I guess they should remember, read below).

Giving your stated usage patterns, and the symptoms, I'm wondering if
possibly the system is doing a Clone() of the first validator you create
to store a copy of the validator rather than the original, which would
cause the first validator to be garbage-collected before its "aux"
object is called.

<snip>

then this might be the problem.

This shouldn't be a problem, as I understand it, this is the normal
behaviour.

From the docs: All validator classes must implement the Clone function,

which returns an identical copy of itself. This is because validators
are passed to control constructors as references which must be copied.
[...]

So they are copied at least once.
What I don't understand is why SetWindow is not being called. It seems
to be the way to go.

Yours,
  Javier

Robin Dunn wrote:

I believe you are right but I don't know how to write this correctly.
I need to catch EVT_TEXT but for that I need the control which will be
causing the event

No you don't. If a window has a validator then it gets all the events
first. Just bind the EVT_TEXT to the validator itself.

I though about this since that is what I do with EVT_CHAR but what Id
should I use? If I'm not mistaken: EVT_TEXT(window, Id, function), right?

Javier

So they are copied at least once.
What I don't understand is why SetWindow is not being called. It
seems to be the way to go.

This may be another case where the C++ base class says:

  foo->bar()

And your Python bar() method gets passed over because C++'s virtual
method tables and Python's dynamic dispatch and don't talk to each
other.

I get burned by this all the time. I'm used to being able to
subclass-and-override to customize software, but in wxPython, you can
only do this when a special "Py" version is provided (wxPyPanel,
wxPyWindow, ...). You can poke at the library to see which ones are
there and which ones aren't:

from wxPython import wx
wx.wxPyPanel

<class wxPython.windows2.wxPyPanel at 0x844a48c>

wx.wxPyButton

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'module' object has no attribute 'wxPyButton'

···

On Monday 24 March 2003 06:47 pm, Javier Ruere wrote:

--
Chuck
http://ChuckEsterbrook.com

Minor correction. In C++, I suppose that would be:

  bar()

or:
  this->bar()

···

On Monday 24 March 2003 07:24 pm, Chuck Esterbrook wrote:

This may be another case where the C++ base class says:

        foo->bar()

--
Chuck
http://ChuckEsterbrook.com

Chuck Esterbrook <ChuckEsterbrook@yahoo.com> writes:

I get burned by this all the time. I'm used to being able to
subclass-and-override to customize software, but in wxPython, you can
only do this when a special "Py" version is provided (wxPyPanel,
wxPyWindow, ...). You can poke at the library to see which ones are
there and which ones aren't:

>>> from wxPython import wx
>>> wx.wxPyPanel
<class wxPython.windows2.wxPyPanel at 0x844a48c>
>>> wx.wxPyButton
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'module' object has no attribute 'wxPyButton'

Couldn't resist:

    >>> import wx
    >>> [item for item in dir(wx) if item.startswith('Py')]
    ['PyApp', 'PyAppPtr', 'PyApp_GetMacAboutMenuItemId',
    'PyApp_GetMacDefaultEncodingIsPC', 'PyApp_GetMacExitMenuItemId',
    'PyApp_GetMacHelpMenuTitleName',
    'PyApp_GetMacPreferencesMenuItemId',
    'PyApp_GetMacSupportPCMenuShortcuts',
    'PyApp_SetMacAboutMenuItemId', 'PyApp_SetMacDefaultEncodingIsPC',
    'PyApp_SetMacExitMenuItemId', 'PyApp_SetMacHelpMenuTitleName',
    'PyApp_SetMacPreferencesMenuItemId',
    'PyApp_SetMacSupportPCMenuShortcuts', 'PyAssertionError',
    'PyBitmapDataObject', 'PyBitmapDataObjectPtr', 'PyCommandEvent',
    'PyCommandEventPtr', 'PyControl', 'PyControlPtr',
    'PyDataObjectSimple', 'PyDataObjectSimplePtr',
    'PyDeadObjectError', 'PyDefaultPosition', 'PyDefaultSize',
    'PyDropTarget', 'PyDropTargetPtr', 'PyEvent', 'PyEventPtr',
    'PyLog', 'PyLogPtr', 'PyOnDemandOutputWindow', 'PyPanel',
    'PyPanelPtr', 'PyPen', 'PyPenPtr', 'PySimpleApp', 'PySizer',
    'PySizerPtr', 'PyTextDataObject', 'PyTextDataObjectPtr',
    'PyTimer', 'PyTimerPtr', 'PyTipProvider', 'PyTipProviderPtr',
    'PyTypeCast', 'PyValidator', 'PyValidatorPtr', 'PyWidgetTester',
    'PyWindow', 'PyWindowPtr', 'Py_isinstance']

···

--
Patrick K. O'Brien
Orbtech http://www.orbtech.com/web/pobrien
-----------------------------------------------
"Your source for Python programming expertise."
-----------------------------------------------

If you want to really impress me, show me code that says which methods
can be overridden and format the results. :wink:

Seriously, if I remember correctly from a Robin-post, a PyClass doesn't
necessarily guarantee that every method you see in the documentation
can be overridden. Is it just a simple matter of doing a dir() on the
particular PyClass to find out? Or would that also show methods that
can't be overridden?

···

On Monday 24 March 2003 07:32 pm, Patrick K. O'Brien wrote:

Chuck Esterbrook <ChuckEsterbrook@yahoo.com> writes:
> I get burned by this all the time. I'm used to being able to
> subclass-and-override to customize software, but in wxPython, you
> can only do this when a special "Py" version is provided
> (wxPyPanel, wxPyWindow, ...). You can poke at the library to see
> which ones are
>
> there and which ones aren't:
> >>> from wxPython import wx
> >>> wx.wxPyPanel
>
> <class wxPython.windows2.wxPyPanel at 0x844a48c>
>
> >>> wx.wxPyButton
>
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> AttributeError: 'module' object has no attribute 'wxPyButton'

Couldn't resist:
    >>> import wx
    >>> [item for item in dir(wx) if item.startswith('Py')]

--
Chuck
http://ChuckEsterbrook.com

Chuck,
  I'm aware of this little issue but I thought that using wxPyValidator
would help me here (still hope it does).

Javier

Chuck Esterbrook wrote:

···

On Monday 24 March 2003 06:47 pm, Javier Ruere wrote:

So they are copied at least once.
What I don't understand is why SetWindow is not being called. It
seems to be the way to go.

This may be another case where the C++ base class says:

  foo->bar()

And your Python bar() method gets passed over because C++'s virtual
method tables and Python's dynamic dispatch and don't talk to each
other.

I get burned by this all the time. I'm used to being able to
subclass-and-override to customize software, but in wxPython, you can
only do this when a special "Py" version is provided (wxPyPanel,
wxPyWindow, ...). You can poke at the library to see which ones are
there and which ones aren't:

from wxPython import wx
wx.wxPyPanel

<class wxPython.windows2.wxPyPanel at 0x844a48c>

wx.wxPyButton

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'module' object has no attribute 'wxPyButton'

At this point, I'm wondering if there's a simple way to introspect what
methods can be overriden (other than just trying them out and finding
out afterwards). Maybe Patrick or Robin know a trick in this area....

···

--
Chuck
http://ChuckEsterbrook.com

On Monday 24 March 2003 07:57 pm, Javier Ruere wrote:

Chuck,
  I'm aware of this little issue but I thought that using
wxPyValidator would help me here (still hope it does).

Javier

Chuck Esterbrook wrote:
> On Monday 24 March 2003 06:47 pm, Javier Ruere wrote:
>>So they are copied at least once.
>>What I don't understand is why SetWindow is not being called. It
>>seems to be the way to go.
>
> This may be another case where the C++ base class says:
>
> foo->bar()
>
> And your Python bar() method gets passed over because C++'s virtual
> method tables and Python's dynamic dispatch and don't talk to each
> other.
>
> I get burned by this all the time. I'm used to being able to
> subclass-and-override to customize software, but in wxPython, you
> can only do this when a special "Py" version is provided
> (wxPyPanel, wxPyWindow, ...). You can poke at the library to see
> which ones are
>
> there and which ones aren't:
>>>>from wxPython import wx
>>>>wx.wxPyPanel
>
> <class wxPython.windows2.wxPyPanel at 0x844a48c>
>
>>>>wx.wxPyButton
>
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> AttributeError: 'module' object has no attribute 'wxPyButton'

---------------------------------------------------------------------
To unsubscribe, e-mail:
wxPython-users-unsubscribe@lists.wxwindows.org For additional
commands, e-mail: wxPython-users-help@lists.wxwindows.org

Javier Ruere wrote:

Robin Dunn wrote:

I believe you are right but I don't know how to write this correctly.
I need to catch EVT_TEXT but for that I need the control which will be
causing the event

No you don't. If a window has a validator then it gets all the events
first. Just bind the EVT_TEXT to the validator itself.

I though about this since that is what I do with EVT_CHAR but what Id
should I use? If I'm not mistaken: EVT_TEXT(window, Id, function), right?

wxID_ANY (-1)

···

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

Chuck Esterbrook wrote:

At this point, I'm wondering if there's a simple way to introspect what methods can be overriden (other than just trying them out and finding out afterwards). Maybe Patrick or Robin know a trick in this area....

In general, if there is a base_MethodName then MethodName is overridable. The exception is if the method is a pure virtual in C++ then there is no base_...

BTW, it looks like there is a new feature added to the newset version of SWIG (just a few days old) that, if I understand it correctly, will make it easy to allow any virtual to be overridable in Python. I've decided that I will try to migrate the 2.5 branch to SWIG 1.3.x and see what I can do with it. When 2.5 goes "stable" it will probably end up being 3.0 if the C++ guys keep to the new schedule so that sounds like a good time to make possibly big changes...

···

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

Robin,
  Thank you very much for your help.
  In this thread I learned a lot about validators thanks to Mike Fletcher
and you.

Yours,
  Javier

Robin Dunn wrote:

···

No you don't. If a window has a validator then it gets all the events
first. Just bind the EVT_TEXT to the validator itself.

I though about this since that is what I do with EVT_CHAR but what Id
should I use? If I'm not mistaken: EVT_TEXT(window, Id, function), right?

wxID_ANY (-1)