This is a short overview of how event propagation works in wxPython, demonstrated on a small example.

What Objects are Involved

Process Overview

Technically, what happens is this:

What are the steps that the wxEventHandler goes through?

This is fairly complicated; If you are not using validators, and you are not using subclasses, and if you are not pushing special purpose event handlers, or any other of these weird things, then simply consider:

Some Things about Window Hierarchy Propagation

Events do not propagate beyond dialogs. They do propagate beyond Frames. This is because there are so many dialogs, but Frames tend to be a bit more "controlled."

You can SetExtraStyle(wx.WS_EX_BLOCK_EVENTS) to make another window block events, as if it were a dialog.

Propagation Level. In wxPython Events will propagate up the window hierarchy if they have a propagation level >0. If that is the case, then the ShouldPropagate method of the wx.Event returns True. If you want to get the numerical propagation level of the event, use the StopPropagation method. It returns the propagation level. (Don't forget to call ResumePropagation afterwards).

The propagation level determines how far the event will propagate. Suppose the propagation level is 1. Then the event will only propagate to a window's parent. If it has a level of 2, it will propagate to the window's parent and to its grandparent. If it has a level of sys.maxint, it will propagate up the whole window hierarchy. (Stopping at Dialog boundaries, but not Frame boundaries.)

By default, only wx.CommandEvents will propagate.

A typical example of an event not propagated is the wx.EVT_KEY_DOWN. It is send only to the control having the focus, and will not propagate to its parent.

To see what is happening have a look at the following example and play with it. Just set some different propagation levels in the OnKeyText method and see what happens.

Code Sample

   1 import wx
   3 class MainFrame(wx.Frame):
   4     def __init__(self, parent, ID, title):
   5         wx.Frame.__init__(self, parent, ID, title,
   6                           wx.DefaultPosition, wx.Size(200, 100))
   8         Panel = wx.Panel(self, -1)
   9         TopSizer = wx.BoxSizer(wx.VERTICAL)
  10         Panel.SetSizer(TopSizer)
  12         Text = wx.TextCtrl(Panel, -1, "Type text here")
  13         TopSizer.Add(Text, 1, wx.EXPAND)
  15         Text.Bind(wx.EVT_KEY_DOWN, self.OnKeyText)
  16         Panel.Bind(wx.EVT_KEY_DOWN, self.OnKeyPanel)
  17         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyFrame)
  19     def OnKeyText(self, event):
  20         print "OnKeyText"
  21         print "\tShould Propagate %i" % event.ShouldPropagate()
  22         Level = event.StopPropagation()
  23         print "\tPropagate level %i" % Level
  24         # Try: event.ResumePropagation(x), x=1,2,3,...
  25         event.ResumePropagation(Level)
  26         event.Skip()
  28     def OnKeyPanel(self, event):
  29         print "OnKeyPanel"
  30         print "\tShould Propagate %i" % event.ShouldPropagate()
  31         Level = event.StopPropagation()
  32         print "\tPropagate level %i" % Level
  33         event.ResumePropagation(Level)
  34         event.Skip()
  36     def OnKeyFrame(self, event):
  37         print "OnKeyFrame"
  38         print "\tShould Propagate %i" % event.ShouldPropagate()
  39         Level = event.StopPropagation()
  40         print "\tPropagate level %i" % Level
  41         event.ResumePropagation(Level)
  42         event.Skip()
  44 class MyApp(wx.App):
  45     def OnInit(self):
  46         Frame = MainFrame(None, -1, "Event Propagation Demo")
  47         Frame.Show(True)
  48         self.SetTopWindow(Frame)
  49         return True
  51 if __name__ == '__main__':
  52     App = MyApp(0)
  53     App.MainLoop()

See Also


Any comments and/or corrections welcome. Feel free to edit this page, or send comments to

EventPropagation (last edited 2008-03-11 10:50:30 by localhost)