wxPython - Event Handling

Unlike a console mode application, which is executed in a sequential manner, a GUI based application is event driven. Functions or methods are executed in response to user’s actions like clicking a button, selecting an item from collection or mouse click, etc., called events.
Data pertaining to an event which takes place during the application’s runtime is stored as object of a subclass derived from wx.Event. A display control (such as Button) is the source of event of a particular type and produces an object of Event class associated to it. For instance, click of a button emits a wx.CommandEvent. This event data is dispatched to event handler method in the program. wxPython has many predefined event binders. An Event binder encapsulates relationship between a specific widget (control), its associated event type and the event handler method.
For example, to call OnClick() method of the program on a button’s click event, the following statement is required −
self.b1.Bind(EVT_BUTTON, OnClick)

Bind() method is inherited by all display objects from wx.EvtHandler class. EVT_.BUTTON here is the binder, which associates button click event to OnClick() method.
In the following example, the MoveEvent, caused by dragging the top level window – a wx.Frame object in this case – is connected to OnMove() method using wx.EVT_MOVE binder. The code displays a window. If it is moved using mouse, its instantaneous coordinates are displayed on the console.
import wx
  
class Example(wx.Frame): 
            
   def __init__(self, *args, **kw): 
      super(Example, self).__init__(*args, **kw)  
      self.InitUI() 
           
   def InitUI(self): 
      self.Bind(wx.EVT_MOVE, self.OnMove) 
      self.SetSize((250, 180)) 
      self.SetTitle('Move event') 
      self.Centre() 
      self.Show(True)
		   
   def OnMove(self, e): 
      x, y = e.GetPosition() 
      print "current window position x = ",x," y= ",y 
         
ex = wx.App() 
Example(None) 
ex.MainLoop()   
The above code produces the following output −
current window position x = 562  y = 309
current window position x = 562  y = 309
current window position x = 326  y = 304
current window position x = 384  y = 240
current window position x = 173  y = 408
current window position x = 226  y = 30
current window position x = 481  y = 80
Some of the subclasses inherited from wx.Event are listed in the following table −
wxKeyEvent
Occurs when a key is presses or released
wxPaintEvent
Is generated whenever contents of the window needs to be redrawn
wxMouseEvent
Contains data about any event due to mouse activity like mouse button pressed or dragged
wxScrollEvent
Associated with scrollable controls like wxScrollbar and wxSlider
wxCommandEvent
Contains event data originating from many widgets such as button, dialogs, clipboard, etc.
wxMenuEvent
Different menu-related events excluding menu command button click
wxColourPickerEvent
wxColourPickerCtrl generated events
wxDirFilePickerEvent
Events generated by FileDialog and DirDialog
Events in wxPython are of two types. Basic events and Command events. A basic event stays local to the window in which it originates. Most of the wxWidgets generate command events. A command event can be propagated to window or windows, which are above the source window in class hierarchy.
Following is a simple example of event propagation. The complete code is −
import wx
  
class MyPanel(wx.Panel): 
     
   def __init__(self, parent): 
      super(MyPanel, self).__init__(parent)
		
      b = wx.Button(self, label = 'Btn', pos = (100,100)) 
      b.Bind(wx.EVT_BUTTON, self.btnclk) 
      self.Bind(wx.EVT_BUTTON, self.OnButtonClicked) 
		
   def OnButtonClicked(self, e): 
         
      print 'Panel received click event. propagated to Frame class' 
      e.Skip()  
		
   def btnclk(self,e): 
      print "Button received click event. propagated to Panel class" 
      e.Skip()
		
class Example(wx.Frame):

   def __init__(self,parent): 
      super(Example, self).__init__(parent)  
         
      self.InitUI() 

   def InitUI(self):
	
      mpnl = MyPanel(self) 
      self.Bind(wx.EVT_BUTTON, self.OnButtonClicked)
		
      self.SetTitle('Event propagation demo') 
      self.Centre() 
      self.Show(True)
		
   def OnButtonClicked(self, e): 
         
      print 'click event received by frame class' 
      e.Skip()
		
ex = wx.App() 
Example(None) 
ex.MainLoop()
In the above code, there are two classes. MyPanel, a wx.Panel subclass and Example, a wx.Frame subclass which is the top level window for the program. A button is placed in the panel.
This Button object is bound to an event handler btnclk() which propagates it to parent class (MyPanel in this case). Button click generates a CommandEvent which can be propagated to its parent by Skip() method.
MyPanel class object also binds the received event to another handler OnButtonClicked(). This function in turn transmits to its parent, the Example class. The above code produces the following output −
Button received click event. Propagated to Panel class. 
Panel received click event. Propagated to Frame class. 
Click event received by frame class.