..  Copyright (C)  Brad Miller, David Ranum, Jeffrey Elkner, Peter Wentworth, Allen B. Downey, Chris
    Meyers, and Dario Mitchell.  Permission is granted to copy, distribute
    and/or modify this document under the terms of the GNU Free Documentation
    License, Version 1.3 or any later version published by the Free Software
    Foundation; with Invariant Sections being Forward, Prefaces, and
    Contributor List, no Front-Cover Texts, and no Back-Cover Texts.  A copy of
    the license is included in the section entitled "GNU Free Documentation
    License".

.. qnum::
   :prefix: gui-7-
   :start: 1

Low-Level Event Processing
==========================

In the previous lessons you learned how to associate simple user actions with
the most common user events, such as clicking on a button. For
simple GUI programs this is typically sufficient. But for more complex programs
you might need to process "lower level" events, such as recognizing when
the user's cursor is over a widget, or when a widget becomes the focus
of user input. To handle these types of events you need to implement
**event binding**. This lesson provides an overview of how to process any
event that happens on a computer. We will not use these techniques in
most of the simple GUI programs we discuss, but you should be aware of
what is possible.


Focus
=====

Remember from our previous discussion that the operating system is in control
of your computer's screen, keyboard, mouse, and other input devices. When
the user interacts with these input devices the operating system generates
``event objects`` that capture specific event information. Your computer is running
multiple processes at any given time, so how does
the computer know which process to send an event to? All GUI operating systems
have the concept of an "active window." Only the "active window" receives events.
We say that the "active window" has the **focus** of the user. Typically the
application whose window is in front of all other windows on the computer
screen has the operating system's **focus**. Only the process with the **focus**
receives user events; the other running applications do **not** receive
user events.

The concept of **focus** goes further than the applications running on a
computer. Inside an application, only one widget at a time can have the
**focus** of the user. The widget with the **focus** is the widget that
receives keyboard events. For example, suppose you had a GUI interface
that contained two different ``Entry`` widgets. If the user hits an "a"
key, which widget has an "a" added to their existing text? It is the widget
that currently has the **focus**.

Event Binding
=============

When your program has the **focus** it can potentially receive many more
events than it desires to process. For example, you may not care that the
pointing device just moved one pixel to the right. All "low level" user
events are ignored by your program unless you specifically request that
a particular type of event be sent to a specific function in your program.
The task of associating a specific ``event handler`` function with a specific
"low level" event is called **binding**.

An event is always **bound** to a specific widget. For example, if you wanted
to know when the cursor of a pointing device has moved over a widget, you would
bind an  ``"<Enter>"`` event to the widget and specify a function to call when the
event happens. This is done with the ``.bind(event_description, event_handler)``
method of a widget. Once this bind operation is complete and the
application's main event loop has started, every time a pointing device is
moved over the widget, the event handler will be called.

Here is an example of binding an ``"<Enter>"`` event to a Button.

.. code-block:: python

  def process_event(event):
    print("The process_event function was called.")

  my_button = tk.Button(application_window, text="Example")
  my_button.bind("<Enter>", process_event)

It is best practice to "stub out" event handlers and verify that events are
being processed correctly before you start developing an application's
actual processing code. Here is an example of a "stubbed" out ``event handler``:

.. code-block:: python

  def my_function():
    print("my_function was called.")

Event Descriptors
=================

An event represents an action that needs to be processed. Events are
caused by a user when they click in a window or type on the keyboard.
Events can also be generated by software, such as a request to redraw the
application's window after changes have been made. In a GUI program,
**all** processing is done by responding to events.

In Tkinter, events are defined as strings using a pre-defined syntax. The general format
of an event description is ``<modifier-type-detail>``, where the ``modifier``
and ``detail`` portions are optional. For example, a ``<Button>`` event is
generated by any change of state of any mouse button, while a ``<Shift-Button>``
event will only be generated if the mouse state changes while the SHIFT key
on the keyboard is down. And a ``<Shift-Button-1>`` event will only be generated
if the left mouse button (associated with the number 1) changes state.
Below is a list of the most widely used events along with a brief description
of each one. You can add or remove ``modifier`` and ``detail`` values to make
events more or less specific.

=============================  ====================================================================
Pointer Related Events         Description
=============================  ====================================================================
``"<ButtonPress-1>"``          The left mouse button was pressed.
``"<ButtonPress-2>"``          The middle mouse button was pressed.
``"<ButtonPress-3>"``          The right mouse button was pressed.
``"<B1-Motion>"``              With the left mouse button held down, the mouse changed location.
``"<B2-Motion>"``              With the middle mouse button held down, the mouse changed location.
``"<B3-Motion>"``              With the right mouse button held down, the mouse changed location.
``"<ButtonRelease-1>"``        The left mouse button was released.
``"<Double-Button-1>"``        The left mouse button was double-clicked.
``"<Enter>"``                  The mouse pointer just moved over a particular widget.
``"<Leave>"``                  The mouse pointer is no longer over a particular widget.
``"<FocusIn>"``                A widget just received the keyboard focus.
``"<FocusOut>"``               A widget just lost the keyboard focus.
``"<Configure>"``              A widget just changed its size or position.
=============================  ====================================================================

=============================  ====================================================================
Keyboard Related Events        Description
=============================  ====================================================================
``"<Key>"``                    The user pressed any key on the keyboard.
``"<Return>"``                 The user pressed the Enter key.
``"<Backspace>"``              The user pressed the Backspace key.
``"<Tab>"``                    The user pressed the Tab key.
``"<Escape>"``                 The user pressed the Escape key.
``"<Prior>"``                  The user pressed the Page-up key.
``"<Next>"``                   The user pressed the Page-down key.
``"<Up>"``                     The user pressed the up arrow key.
``"<Down>"``                   The user pressed the down arrow key.
``"<Left>"``                   The user pressed the left arrow key.
``"<Right>"``                  The user pressed the right arrow key.
``"<F1>"``                     The user pressed the F1 key.
``"<F2>"``                     The user pressed the F2 key.
``"<a>"``                      The user pressed the "a" key.
``"<b>"``                      The user pressed the "b" key.
``"<c>"``                      The user pressed the "c" key.
``"<Shift-Up>"``               The user pressed the up arrow key while the shift key was down.
``"<Alt-Up>"``                 The user pressed the up arrow key while the alt key was down.
``"<Control-Up>"``             The user pressed the up arrow key while the control key was down
etc...
=============================  ====================================================================

Event Objects
=============

When a user generates an event, or the software generates an event, an ``event
object`` is created. This object is automatically passed to the function that
is registered to handle the event. Every event handler function that is **bound**
to an event using the ``.bind(event_description, function_handler)`` function
must be defined to receive one parameter, an ``event object``.

An ``event object`` contains the following attributes.

========================  ====================================================================
Event Object Attribute    Description
========================  ====================================================================
``.widget``               The widget this event was **bound** to. This is a reference to a
                          ``Tkinter`` widget instance; it is not a string name.
``.x``, ``.y``            The current mouse position, relative to the application's window, in pixels.
``.x_root``, ``.y_root``  The current mouse position relative to the upper left corner of the
                          screen, in pixels.
``.char``                 For keyboard events only, this is the character code of the key
                          pressed or released as a string.
``.keysym``               For keyboard events only, the key symbol.
``.keycode``              For keyboard events only, the key code (i.e., the key's Unicode
                          decimal value).
``.num``                  For mouse button events only, the button number.

``.width``, ``.height``   For configure events only, the new size of the widget, in pixels.
========================  ====================================================================

A typical event handler will use the values in the ``event object`` it receives
to perform an appropriate action related to the event. For example,

.. code-block:: python

  def process_event(event):
    if event.x > 10 and event.y > 20:
      # do something

Event Processing
================

The operating system generates events in the order the user or the program
creates them. An application's GUI event loop receives the events in this
same order and then calls the appropriate event handler. Therefore,
events are processed in the same order they are created.

Events can't be processed unless the application's GUI event-loop
is running. If an individual event handler takes a long time to process an
event, other events will get "queued up" waiting for a chance to be processed.
It is considered bad GUI programming for any event handler to take
up too much processing time. An event handler should do as little processing
as possible to accomplish its intended task and then quit. This returns
control of the application back to the event loop.

Events are always associated with a widget. If you want to know every event
that happens inside an application's window, then bind events to the widget
that is your application's window. If you only want to know about button
click events on a particular button, then bind an event handler to that
specific button. In general, events should be associated with the most
specific widget possible.

Some widgets, such as a Notebook that implements a tabbed set of frames, have
predefined events that are used to manipulate them. These are called "bind_class"
event bindings and they bind certain events to all instances of a particular
widget type. In general you should not modify or change these types of
event bindings because a user expects a certain behaviour from a particular
type of widget and changing that behaviour can make the entire user interface
confusing to a user.


.. index:: focus, event binding, event descriptors, event object

