[wxPython] confusion with custom event handling

Hi everyone,

I have an application that responds to Drag and Drop. When a drop
occurs, I have several widgets that need to be notified that an event
occurred. This sounded like a perfect candidate for a custom event. So
I created a custom event as follows...

DRAG_DROP_CLEAR = wxNewEventType()

def EVT_DRAG_DROP_CLEAR(parent, ctrl, func):
    parent.Connect (ctrl.GetId(), -1, DRAG_DROP_CLEAR , func)

class DragDropClearEvent(wxPyCommandEvent):
    def __init__(self, evtType, id):
        wxPyCommandEvent.__init__(self, evtType, id)
        
class DragDropHandler(wxEvtHandler):
    def __init__(self, parent):
        wxEvtHandler.__init__(self)
        self.Parent = parent

        EVT_DRAG_DROP_CLEAR(self, parent, self.OnClear)
        
    def OnClear(self, event):
        self.Parent.DropVariable = None
        #additional processing snipped for brevity

For each of the widgets that are to respond to the event, I push an
instance of the new wxEvtHandler in the widget's __init__. This was
accomplished via
    self.GetEventHandler().PushEventHandler(DragDropHandler(self))

The problem that I am having is that I have to know the ID of the widget
that is to receive the event at the time that I create the new event
object.

During the drop processing, I created an event object, and used
frame.ProcessEvent() and this did not seem to go anywhere. I also tried
wxPostEvent() with the same results. When I used ProcessEvent() for
each of the widgets concerned, than it worked fine. To work this way
then, I had to create an event for each of the widgets that needed to be
notified.

Since a wxPyCommandEvent is tied to a particular id, it seems like I
should be using something else. How can I define a generic event that
when sent to the toplevel frame of my application will be received by
all the widgets that use the new EventHandler?

Thanks,

Bryan

For each of the widgets that are to respond to the event, I push an
instance of the new wxEvtHandler in the widget's __init__. This was
accomplished via
    self.GetEventHandler().PushEventHandler(DragDropHandler(self))

The problem that I am having is that I have to know the ID of the widget
that is to receive the event at the time that I create the new event
object.

Actually, the ID in the event is usually the widget that generated the
event, not the one that receives it. When you use EVT_BUTTON in a frame
then the ID you specify is that of the button not the frame, and the button
doesn't need to know the ID of the receiver of the event when he generates
and sends it.

OTOH, If you use -1 for the ID in the EVT_* or in the .Connect then any ID
will match. This means that EVT_BUTTON(self, -1, self.OnButton) will cause
OnButton to be called for any button event from any button contained in
self.

During the drop processing, I created an event object, and used
frame.ProcessEvent() and this did not seem to go anywhere. I also tried
wxPostEvent() with the same results. When I used ProcessEvent() for
each of the widgets concerned, than it worked fine. To work this way
then, I had to create an event for each of the widgets that needed to be
notified.

Since a wxPyCommandEvent is tied to a particular id, it seems like I
should be using something else. How can I define a generic event that
when sent to the toplevel frame of my application will be received by
all the widgets that use the new EventHandler?

You can't. wxCommandEvents travel UP the containment heirarchy, not DOWN
it.

If you really need to send the event to all children of a particular window
then you can either do a recursive descent using GetChildren() and sending
the event to each in turn. (You probably want to switch to wxPyEvent so
only the given window is tried for a match and the events don't travel up
the containment heirarchy each time.)

An easier method would be for the frame to just keep a list of those
children that need to be notified and either send the event to just them.
Of course once you have the list of windows you may as well save the time
for event processing and call a notification method on them directly.

···

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