Are you making an app in which you catch and process key events? Are there too many key events, and your OnKeyDown handler resembles a dish of spaghetti with elif sauce?

You may want to consider using the following approach, which is an example of using the Strategy Pattern.

Define the following class:

   1 class Key(object):    
   2     '''A key combination.'''
   3 
   4     def __init__(self, key_code, cmd=False, alt=False, shift=False):
   5 
   6         self.key_code = key_code        
   7         '''The numerical code of the pressed key.'''
   8         
   9         self.cmd = cmd
  10         '''Flag saying whether the ctrl/cmd key was pressed.'''
  11         
  12         self.alt = alt
  13         '''Flag saying whether the alt key was pressed.'''
  14         
  15         self.shift = shift
  16         '''Flag saying whether the shift key was pressed.'''
  17         
  18         
  19     @staticmethod
  20     def get_from_key_event(event):
  21         '''Construct a Key from a wx.EVT_KEY_DOWN event.'''
  22         return Key(event.GetKeyCode(), event.CmdDown(),
  23                    event.AltDown(), event.ShiftDown())
  24     
  25     def __hash__(self):
  26         return hash(tuple(sorted(tuple(vars(self)))))
  27     
  28     def __eq__(self, other):
  29         if not isinstance(other, Key):
  30             return NotImplemented
  31         return self.key_code == other.key_code and \
  32                self.cmd == other.cmd and \
  33                self.shift == other.shift and \
  34                self.alt == other.alt

Now in your Frame's __init__, you should call a method like this:

   1     def __init_key_handlers(self):
   2         '''Initialize key shortcuts.'''
   3         
   4         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
   5         
   6         # Now you define handlers for various keys:
   7 
   8         def on_home():
   9             '''Go to home.'''
  10             # ...
  11 
  12                 
  13         def on_end():
  14             '''Go to end.'''
  15             # ...
  16 
  17         def on_command_left():
  18             '''Go left hard.'''
  19             # ...
  20         
  21         # This is the big dict that maps keys to their handlers:        
  22 
  23         self.key_handlers = {
  24             wx_tools.Key(wx.WXK_HOME): on_home,
  25             wx_tools.Key(wx.WXK_END): on_end,
  26             wx_tools.Key(wx.WXK_LEFT, cmd=True): on_command_left,
  27         }    

And also define the handler for EVT_KEY_DOWN:

   1     def OnKeyDown(self, event):
   2         '''wx.EVT_KEY_DOWN handler.'''
   3         key = Key.get_from_key_event(event)
   4         handler = self.key_handlers.get(key, None)
   5         if handler:
   6             handler()
   7         else:
   8             event.Skip()

That's it! Now your key handlers will be a little bit more maintainable.

Processing key events in a strategy pattern (last edited 2010-06-25 20:28:01 by 87)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.