It is often convenient to attach more than one event handler for an event. EventDispatcher allows you to stack event handlers upon one another, rather than replacing them outright. The event will propogate from the top of the stack to the bottom, but can be stopped by any handler along the way.
To push an event handler onto the stack, use the push_handlers method:
def on_key_press(symbol, modifiers): if symbol == key.SPACE fire_laser() window.push_handlers(on_key_press)
As a convenience, the @event decorator can be used as an alternative to push_handlers:
@window.event def on_key_press(symbol, modifiers): if symbol == key.SPACE fire_laser()
One use for pushing handlers instead of setting them is to handle different parameterisations of events in different functions. In the above example, if the spacebar is pressed, the laser will be fired. After the event handler returns control is passed to the next handler on the stack, which on a Window is a function that checks for the ESC key and sets the has_exit attribute if it is pressed. By pushing the event handler instead of setting it, the application keeps the default behaviour while adding additional functionality.
You can prevent the remaining event handlers in the stack from receiving the event by returning a true value. The following event handler, when pushed onto the window, will prevent the escape key from exiting the program:
def on_key_press(symbol, modifiers): if symbol == key.ESCAPE: return True window.push_handlers(on_key_press)
You can push more than one event handler at a time, which is especially useful when coupled with the pop_handlers function. In the following example, when the game starts some additional event handlers are pushed onto the stack. When the game ends (perhaps returning to some menu screen) the handlers are popped off in one go:
def start_game(): def on_key_press(symbol, modifiers): print 'Key pressed in game' return True def on_mouse_press(x, y, button, modifiers): print 'Mouse button pressed in game' return True window.push_handlers(on_key_press, on_mouse_press) def end_game(): window.pop_handlers()
Note that you do not specify which handlers to pop off the stack -- the entire top "level" (consisting of all handlers specified in a single call to push_handlers) is popped.
You can apply the same pattern in an object-oriented fashion by grouping related event handlers in a single class. In the following example, a GameEventHandler class is defined. An instance of that class can be pushed on and popped off of a window:
class GameEventHandler(object): def on_key_press(self, symbol, modifiers): print 'Key pressed in game' return True def on_mouse_press(self, x, y, button, modifiers): print 'Mouse button pressed in game' return True game_handlers = GameEventHandler() def start_game() window.push_handlers(game_handlers) def stop_game() window.pop_handlers()