1.. include:: headings.inc 2 3 4.. _events and event handling: 5 6============================================== 7|phoenix_title| **Events and Event Handling** 8============================================== 9 10 11Like with all the other GUI frameworks, the control of flow in 12wxPython applications is event-based: the program normally performs 13most of its actions in response to the events generated by the 14user. These events can be triggered by using the input devices (such 15as keyboard, mouse, joystick) directly or, more commonly, by a 16standard control which synthesizes such input events into higher level 17events: for example, a :ref:`wx.Button` can generate a click event when 18the user presses the left mouse button on it and then releases it 19without pressing ``Esc`` in the meanwhile. There are also events which 20don't directly correspond to the user actions, such as 21:ref:`wx.TimerEvent`. 22 23But in all cases wxPython represents these events in a uniform way and 24allows you to handle them in the same way wherever they originate 25from. And while the events are normally generated by wxPython itself, 26you can also do this, which is especially useful when using custom 27events (see :ref:`Custom Event Summary <custom event summary>`). 28 29To be more precise, each event is described by: 30 31- **Event type**: this is simply a value of type `EventType` which 32 uniquely identifies the type of the event. For example, clicking on 33 a button, selecting an item from a list box and pressing a key on 34 the keyboard all generate events with different event types. 35 36- **Event class**: carried by the event: each event has some information 37 associated with it and this data is represented by an object of a 38 class derived from :ref:`wx.Event`. Events of different types can 39 use the same event class, for example both button click and listbox 40 selection events use :ref:`wx.CommandEvent` class (as do all the 41 other simple control events), but the key press event uses 42 :ref:`wx.KeyEvent` as the information associated with it is 43 different. 44 45- **Event source**: :ref:`wx.Event` stores the object which generated the 46 event and, for windows, its identifier (see :ref:`Window Identifiers 47 <window identifiers>`). As it is common to have more than one object 48 generating events of the same type (e.g. a typical window contains 49 several buttons, all generating the same button click event), 50 checking the event source object or its id allows to distinguish 51 between them. 52 53 54 55.. _event handling: 56 57Event Handling 58-------------- 59 60There is one principal way to handle events in wxPython, which uses 61the :meth:`wx.EvtHandler.Bind` call and can be used to bind and unbind 62the handlers dynamically, i.e. during run-time depending on some 63conditions. It also allows the direct binding of events to: 64 65- A handler method in the same or another object. 66- An ordinary function like a static method or a global function. 67- An arbitrary callable object. 68 69 70 71.. _dynamic event handling: 72 73Dynamic Event Handling 74---------------------- 75 76Let us start by looking at the syntax: in any place in your code, but 77usually in the code of the class defining the handler itself, call its 78``Bind()`` method like this:: 79 80 class MyFrame(wx.Frame): 81 def __init__(self, parent): 82 wx.Frame.__init__(self, parent) 83 84 # Other initialization code... 85 86 self.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT) 87 88 89 90Event handlers can be bound at any moment. For example, it's possible 91to do some initialization first and only bind the handlers if and when 92it succeeds. This can avoid the need to test that the object was 93properly initialized in the event handlers themselves. With ``Bind()`` 94they simply won't be called if it wasn't correctly initialized. 95 96As a slight extension of the above, the handlers can also be unbound 97at any time with :meth:`wx.EvtHandler.Unbind` (and maybe rebound 98later). 99 100Almost last but very, very far from least is the flexibility which 101allows to bind an event to: 102 103- A method in another object. 104- An ordinary function like a static method or a global function. 105- An arbitrary function. 106 107 108Let us now look at more examples of how to use different event 109handlers using the two overloads of ``Bind()`` function: first one for 110the object methods and the other one for arbitrary functors (callable 111objects, including simple functions). 112 113In addition to using a method of the object generating the event 114itself, you can use a method from a completely different object as an 115event handler:: 116 117 def OnFrameExit(event): 118 # Do something useful. 119 pass 120 121 class MyFrame(wx.Frame): 122 def __init__(self, parent): 123 wx.Frame.__init__(self, parent) 124 125 # Other initialization code... 126 127 self.Bind(wx.EVT_MENU, OnFrameExit, id=wx.ID_EXIT) 128 129 130 131Note that `MyFrameHandler` doesn't need to derive from 132:ref:`wx.EvtHandler`. 133 134 135 136.. _how events are processed: 137 138How Events are Processed 139------------------------ 140 141The previous sections explain how to define event handlers but don't 142address the question of how exactly wxPython finds the handler to call 143for the given event. This section describes the algorithm used in 144detail. 145 146When an event is received from the windowing system, wxPython calls 147:meth:`wx.EvtHandler.ProcessEvent` on the first event handler object 148belonging to the window generating the event. The normal order of 149event table searching by ``ProcessEvent`` is as follows, with the 150event processing stopping as soon as a handler is found (unless the 151handler calls :meth:`wx.Event.Skip` in which case it doesn't count as 152having handled the event and the search continues): 153 1541. Before anything else happens, :meth:`wx.AppConsole.FilterEvent` is 155 called. If it returns anything but -1 (default), the event handling 156 stops immediately. 157 1582. If this event handler is disabled via a call to 159 :meth:`wx.EvtHandler.SetEvtHandlerEnabled` the next three steps are 160 skipped and the event handler resumes at step (5). 161 1623. If the object is a :ref:`wx.Window` and has an associated validator, 163 :ref:`wx.Validator` gets a chance to process the event. 164 1654. The list of dynamically bound event handlers, i.e., those for which 166 ``Bind()`` was called, is consulted. 167 1685. The event table containing all the handlers defined using the event 169 table macros in this class and its base classes is examined. Notice 170 that this means that any event handler defined in a base class will 171 be executed at this step. 172 1736. The event is passed to the next event handler, if any, in the event 174 handler chain, i.e., the steps (1) to (4) are done for it. Usually 175 there is no next event handler so the control passes to the next 176 step but see :ref:`Event Handlers Chain <event handlers chain>` for 177 how the next handler may be defined. 178 1797. If the object is a :ref:`wx.Window` and the event is set to 180 propagate (by default only event types derived from 181 :ref:`wx.CommandEvent` are set to propagate), then the processing 182 restarts from the step (1) (and excluding the step (7)) for the 183 parent window. If this object is not a window but the next handler 184 exists, the event is passed to its parent if it is a window. This 185 ensures that in a common case of (possibly several) non-window 186 event handlers pushed on top of a window, the event eventually 187 reaches the window parent. 188 1898. Finally, i.e., if the event is still not processed, the 190 :ref:`wx.App` object itself (which derives from 191 :ref:`wx.EvtHandler`) gets a last chance to process it. 192 193 194**Please pay close attention to step 6!** People often overlook or get 195confused by this powerful feature of the wxPython event processing 196system. The details of event propagation up the window hierarchy are 197described in the next section. 198 199 200 201.. _how events propagate upwards: 202 203How Events Propagate Upwards 204^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 205 206As mentioned above, the events of the classes deriving from 207:ref:`wx.CommandEvent` are propagated by default to the parent window if 208they are not processed in this window itself. But although by default 209only the command events are propagated like this, other events can be 210propagated as well because the event handling code uses 211:meth:`wx.Event.ShouldPropagate` to check whether an event should be 212propagated. It is also possible to propagate the event only a limited 213number of times and not until it is processed (or a top level parent 214window is reached). 215 216Finally, there is another additional complication (which, in fact, 217simplifies life of wxPython programmers significantly): when 218propagating the command events up to the parent window, the event 219propagation stops when it reaches the parent dialog, if any. This 220means that you don't risk getting unexpected events from the dialog 221controls (which might be left unprocessed by the dialog itself because 222it doesn't care about them) when a modal dialog is popped up. The 223events do propagate beyond the frames, however. The rationale for this 224choice is that there are only a few frames in a typical application 225and their parent-child relation are well understood by the programmer 226while it may be difficult, if not impossible, to track down all the 227dialogs that may be popped up in a complex program (remember that some 228are created automatically by wxPython). If you need to specify a 229different behaviour for some reason, you can use 230:meth:`wx.Window.SetExtraStyle` (``wx.WS_EX_BLOCK_EVENTS``) explicitly 231to prevent the events from being propagated beyond the given window or 232unset this flag for the dialogs that have it on by default. 233 234Typically events that deal with a window as a window (size, motion, 235paint, mouse, keyboard, etc.) are sent only to the window. Events 236that have a higher level of meaning or are generated by the window 237itself (button click, menu select, tree expand, etc.) are command 238events and are sent up to the parent to see if it is interested in the 239event. More precisely, as said above, all event classes not deriving 240from :ref:`wx.CommandEvent` (see the :ref:`wx.Event` inheritance 241diagram) do not propagate upward. 242 243In some cases, it might be desired by the programmer to get a certain 244number of system events in a parent window, for example all key events 245sent to, but not used by, the native controls in a dialog. In this 246case, a special event handler will have to be written that will 247override ``ProcessEvent()`` in order to pass all events (or any 248selection of them) to the parent window. 249 250 251.. _event handlers chain: 252 253Event Handlers Chain 254^^^^^^^^^^^^^^^^^^^^ 255 256Step 4 of the event propagation algorithm checks for the next 257handler in the event handler chain. This chain can be formed using 258:meth:`wx.EvtHandler.SetNextHandler`: 259 260.. figure:: _static/images/overviews/overview_events_chain.png 261 :align: center 262 263| 264 265(Referring to the image, if ``A.ProcessEvent`` is called and it doesn't 266handle the event, ``B.ProcessEvent`` will be called and so on...). 267 268Additionally, in the case of :ref:`wx.Window` you can build a stack 269(implemented using :ref:`wx.EvtHandler` double-linked list) using 270:meth:`wx.Window.PushEventHandler`: 271 272.. figure:: _static/images/overviews/overview_events_winstack.png 273 :align: center 274 275| 276 277 278 279(Referring to the image, if ``W.ProcessEvent`` is called, it 280immediately calls ``A.ProcessEvent``; if nor A nor B handle the event, 281then the :ref:`wx.Window` itself is used -- i.e. the dynamically bind 282event handlers and static event table entries of :ref:`wx.Window` are 283looked as the last possibility, after all pushed event handlers were 284tested). 285 286By default the chain is empty, i.e. there is no next handler. 287 288 289.. _custom event summary: 290 291Custom Event Summary 292-------------------- 293 294General approach 295^^^^^^^^^^^^^^^^ 296 297Custom event classes allow you to create more polished-seeming 298controls by allowing the control's user to process updates without 299needing to sub-class the control. However, to effectively use events, 300you normally need to create custom event classes. 301 302This recipe gives you some boilerplate code for creating your own 303custom event classes:: 304 305 import wx 306 import wx.lib.newevent 307 308 SomeNewEvent, EVT_SOME_NEW_EVENT = wx.lib.newevent.NewEvent() 309 SomeNewCommandEvent, EVT_SOME_NEW_COMMAND_EVENT = wx.lib.newevent.NewCommandEvent() 310 311 312You can bind the events normally via either binding syntax:: 313 314 self.Bind(EVT_SOME_NEW_EVENT, self.handler) 315 EVT_SOME_NEW_EVENT(self, self.handler) 316 317 318You can also attach arbitrary data to the event during its creation, 319then post it to whatever window you choose:: 320 321 # Create the event 322 evt = SomeNewEvent(attr1="hello", attr2=654) 323 # Post the event 324 wx.PostEvent(target, evt) 325 326 327When handling events with such arbitrary data, you can fetch the data 328via attributes, named the same as the names passed in during the event 329instance creation. That is, given the two keyword arguments passed to 330``SomeNewEvent`` above:: 331 332 333 def handler(self, evt): 334 # Given the above constructed event, the following is true 335 evt.attr1 == "hello" 336 evt.attr2 == 654 337 338 339 340 341Miscellaneous Notes 342------------------- 343 344 345.. _user generated events vs programmatically generated events: 346 347User Generated Events vs Programmatically Generated Events 348^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 349 350While generically a :ref:`wx.Event` can be generated both by user actions 351(e.g., resize of a :ref:`wx.Window`) and by calls to functions (e.g., 352:meth:`wx.Window.SetSize`), wxPython controls normally send 353:ref:`wx.CommandEvent` -derived events only for the user-generated 354events. The only exceptions to this rule are: 355 356- :meth:`wx.BookCtrlBase.AddPage` No event-free alternatives 357 358- :meth:`wx.BookCtrlBase.AdvanceSelection` No event-free alternatives 359 360- :meth:`wx.BookCtrlBase.DeletePage` No event-free alternatives 361 362- :meth:`wx.Notebook.SetSelection`: Use :meth:`wx.Notebook.ChangeSelection` 363 instead, as :meth:`wx.Notebook.SetSelection` is deprecated 364 365- :meth:`wx.TreeCtrl.Delete`: No event-free alternatives 366 367- :meth:`wx.TreeCtrl.DeleteAllItems`: No event-free alternatives 368 369- :meth:`wx.TreeCtrl.EditLabel`: No event-free alternatives 370 371- All :ref:`wx.TextCtrl` methods 372 373 374:meth:`wx.TextEntry.ChangeValue` can be used instead of 375:meth:`wx.TextEntry.SetValue` but the other functions, such as 376:meth:`wx.TextEntry.Replace` or :meth:`wx.TextCtrl.WriteText` don't 377have event-free equivalents. 378 379 380 381.. _window identifiers: 382 383Window Identifiers 384^^^^^^^^^^^^^^^^^^ 385 386Window identifiers are integers, and are used to uniquely determine 387window identity in the event system (though you can use it for other 388purposes). In fact, identifiers do not need to be unique across your 389entire application as long they are unique within the particular 390context you're interested in, such as a frame and its children. You 391may use the ``wx.ID_OK`` identifier, for example, on any number of 392dialogs as long as you don't have several within the same dialog. 393 394If you pass ``wx.ID_ANY`` or -1 to a window constructor, an identifier 395will be generated for you automatically by wxPython. This is useful 396when you don't care about the exact identifier either because you're 397not going to process the events from the control being created or 398because you process the events from all controls in one place (in 399which case you should specify ``wx.ID_ANY`` in the 400:meth:`wx.EvtHandler.Bind` call as well). The automatically generated 401identifiers are always negative and so will never conflict with the 402user-specified identifiers which must be always positive. 403 404.. seealso:: See :ref:`Standard event identifiers <standard event identifiers>` 405 for the list of standard identifiers available. 406 407 408You can use ``wx.ID_HIGHEST`` to determine the number above which it is 409safe to define your own identifiers. Or, you can use identifiers below 410``wx.ID_LOWEST``. Finally, you can allocate identifiers dynamically 411using :func:`wx.NewIdRef` function too. If you use :func:`wx.NewIdRef` 412consistently in your application, you can be sure that your 413identifiers don't conflict accidentally. 414