wxPython 2.8/2.9 ProcessEvent()

Robin, That confuses me.

Given:
object -> wx.Object -> EvtHandler -> Window -> TopLevelWindow -> Frame

Why the new method ProcessWindowEvent? Why not have wx.Window in the
standard wx modules override EvtHandler's ProcessEvent method with
something like:

class Window(EvtHandler):
    def ProcessEvent(self...)
        # whatever code is in ProcessWindowEvent(),
        # or do
        return super(Window,
self).self.GetPrevEventHandler().ProcessEvent(...)

···

On Oct 25, 4:21 pm, Robin Dunn <ro...@alldunn.com> wrote:

On 10/25/11 12:39 PM, Andrea Gavana wrote:

> Correct, I had huge headaches trying to figure out how to maintain 2
> custom controls I have written supporting both 2.8 and 2.9. Not to
> mention the self.GetEventHandler().ProcessEvent() vs.
> self.ProcessWindowEvent() issue, which I pray will not wreak too much
> havoc to AGW, or I'll have to go through the whole library and apply
> conditional switches all over the place to support 2.8 and 2.9 at the
> same time.

self.GetEventHandler().ProcessEvent() should be the same as
self.ProcessWindowEvent(), and the former should still be doable in 2.9,
is that not the case? The thing that was changed is that it is no
longer allowed to call self.ProcessEvent when self is a window class,
because that bypasses any pushed event handlers or validators on the window.

One other related change that comes to mind is that in 2.9 you need to
pop any pushed event handlers before the window is destroyed as they
will no longer take ownership of those event handler objects.

--
Robin Dunn
Software Craftsmanhttp://wxPython.org

One other related change that comes to mind is that in 2.9 you need to
pop any pushed event handlers before the window is destroyed as they
will no longer take ownership of those event handler objects.

Did I understand that right? The wx.Window class no longer has
ownership of it's EvtHandler?

But then does wx.Window inherit from Evthandler in 2.9?

On a loosely related issue:
Personally I like object -> wx.Object -> wx.EvtHandler -> wx.Window ->
wx.Frame
where TopLevelWindow would be an attribute and not a class.

This way I can create window subclasses, and not frames, as my top
level window, where that window does not have that extra garbage like
titlebars and menus and toolbars and statusbar and other stuff and I
can create my own Toplevel window structure that CAN have agw, aui,
frames, etc as children (which is what I really want) yet still have
that basic wx.Window plumbing.

The hiearchy that turns me on is: wx.Window ->wx.SizerWindow ->
wx.Frame where TopLevel is a property == True or False

def GetTopLevel(self):
    return (True if self.parent is None else False)
def SetTopLevel(self):
    return self.Reparent(None)
TopLevel = property(_GetTopLevel(), _SetTopLevel)

# or something like that; of course then the definition of
wx.Window.IsTopLevel() changes.

Why not use panels? well panels are frames without decorations,
everyone codes on panels expect to take up its entire client area? Why
have a dragpanel when you can have a frame. Why not use a frame?
Frames can not be children of other frames, but windows can be.
Why not use miniframe? I don't like the "dragbar" and it seems harder
to theme a miniframe.

My goal there is to write a custom widget like agw, but in python and
wxpython, not in C++. Where I -could- create my own Doc/View-like
interface for a chat interface I saw somewhere and haven't seen since
(something I've wanted to do for a long time).

A new method is needed because otherwise there would be an infinite recursion. If wxWindow::ProcessEvent was changed to do:

  return GetEventHandler()->ProcessEvent(evt);

then in the case where GetEventHandler returns itself then the same method of the same instance would be called again. And again, and... So instead the new ProcessWindowEvent function has the code above and it is okay for it to end up calling this->ProcessEvent because there will be no recursion.

The reason that the new method was added was to prevent people from calling window.ProcessEvent() without using GetEventHandler, so they would not accidentally skip the pushed event handlers, if any. (See my next message for more about this.)

···

On 10/26/11 10:46 AM, DevPlayer wrote:

Robin, That confuses me.

Given:
object -> wx.Object -> EvtHandler -> Window -> TopLevelWindow -> Frame

Why the new method ProcessWindowEvent? Why not have wx.Window in the
standard wx modules override EvtHandler's ProcessEvent method with
something like:

--
Robin Dunn
Software Craftsman

It does. A wx.Window "is a" wx.EvtHandler, but it can also "have a" collection of wx.EvtHandlers that have been pushed on to it like a stack. In other words, you can have a window hierarchy something like this (ascii art, view with a monospaced font):

···

On 10/26/11 11:17 AM, DevPlayer wrote:

One other related change that comes to mind is that in 2.9 you need to
pop any pushed event handlers before the window is destroyed as they
will no longer take ownership of those event handler objects.

Did I understand that right? The wx.Window class no longer has
ownership of it's EvtHandler?

But then does wx.Window inherit from Evthandler in 2.9?

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

parentWindow |

-----------------
        ^
        >
----------------- ----------------- -------- --------

childWindow |<---| EvtHandlerA |<---| EHB |<---| EHC |

----------------- ----------------- -------- --------
        ^
        >
-----------------

grandchild |

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

If I call childWindow.GetEventHandler then I will get a reference to EHC, and calling its ProcessEvent will cause wx to search for matching handlers in this order: EHC, EHB, EHA, childWindow, and if it's a CommandEvent then it will search parentWindow for a match.

If I call grandchild.GetEventHadnler then I will get a reference to grandchild and ProcessEvents will look therefor matching bindings, followed by EHC, EHB, EHA, childWindow, etc. if it's a command event.

This is not used much from Python but it is a convenient way in C++ to do things like share event handler code between different types of widgets without needing to derive new classes, or changing groups of event bindings at runtime without changing the actual window classes.

BTW, there is a comment in the code that asserts if there are any pushed event handlers still on the stack when a window is destroyed that explains why it is important to pop them off the stack:

     // Any additional event handlers should be popped before the window is
     // deleted as otherwise the last handler will be left with a dangling
     // pointer to this window result in a difficult to diagnose crash later on.
     wxASSERT_MSG( GetEventHandler() == this,
                     wxT("any pushed event handlers must have been removed") );

On a loosely related issue:
Personally I like object -> wx.Object -> wx.EvtHandler -> wx.Window ->
wx.Frame
where TopLevelWindow would be an attribute and not a class.

wx.TopLevelWindow has code that is shared by frames and dialogs, but not other types of wx.Windows. By not having a wx.TopLevelWindow class that code would have to be duplicated in both wx.Frame and wx.Dialog, which is a bad thing.

This way I can create window subclasses, and not frames, as my top
level window, where that window does not have that extra garbage like
titlebars and menus and toolbars and statusbar and other stuff and I
can create my own Toplevel window structure that CAN have agw, aui,
frames, etc as children (which is what I really want) yet still have
that basic wx.Window plumbing.

You can easily turn all of that off for wx.Frame, just use style=0.

Why not use panels? well panels are frames without decorations,

Visually maybe. But in just about every other way that matters they are very different.

--
Robin Dunn
Software Craftsman

Appreciated.