16.9 Tkinter Events

So far, we've seen only the most elementary kind of event handling: the callbacks performed on callables installed with the command= option of buttons and menu entries of various kinds. Tkinter also lets you install callables to call back when needed to handle a variety of events. However, Tkinter does not let you create your own custom events; you are limited to working with events predefined by Tkinter itself.

16.9.1 The Event Object

General event callbacks must accept one argument event that is a Tkinter event object. Such an event object has several attributes describing the event:

char

A single-character string that is the key's code (only for keyboard events)

keysym

A string that is the key's symbolic name (only for keyboard events)

num

Button number (only for mouse-button events); 1 and up

x, y

Mouse position, in pixels, relative to the upper left corner of the widget

x_root , y_root

Mouse position, in pixels, relative to the upper left corner of the screen

widget

The widget in which the event has occurred

16.9.2 Binding Callbacks to Events

To bind a callback to an event in a widget w, call w.bind, describing the event with a string, usually enclosed in angle brackets ('<...>'). The following example prints 'Hello World' each time the user presses the Enter key:

from Tkinter import *

root = Tk(  )
def greet(*ignore): print 'Hello World'
root.bind('<Return>', greet)
root.mainloop(  )

Method tag_bind of classes Canvas and Text, covered earlier in this chapter, lets you bind event callbacks to specific sets of items of a Canvas instance, or to ranges within a Text instance.

16.9.3 Event Names

Frequently used event names, which are almost all enclosed in angle brackets, fall into a few categories.

16.9.3.1 Keyboard events
Key

The user clicked any key. The event object's attribute char tells you which key, but for normal keys only, not for special keys. The event object's attribute keysym is equal to attribute char for letters and digits, is the character's name for punctuation characters, and is the key name for special keys, as covered in the next paragraph.

Special keys

Special keys are associated with event names: F1, F2, ..., up to F12 for function keys; Left, Right, Up, Down for arrow keys; Prior, Next for page-up, page-down; BackSpace, Delete, End, Home, Insert, Print, Tab, for keys so labeled; Escape for the key often labeled Esc; Return for the key often labeled Enter; Caps_Lock, Num_Lock, Scroll_Lock for locking-request keys; Alt_L, Control_L, Shift_L for the modifier keys Alt, Ctrl, Shift (without distinction among the multiple instances of such modifier keys in a typical keyboard). All of these event names are placed within angle brackets, like almost all event names.

Normal keys

Normal keys are associated with event names without surrounding angle bracketsthe only event names to lack such brackets. The event name of each normal key is just the associated character, such as 'w', '1', or '+'. Two exceptions are the Space key, whose event name is '<space>', and the key associated with the less-than character, whose event name is '<less>'.

All key event names can be modified by prefixing 'Alt-', 'Shift-', or 'Control-'. In this case, the whole event name does always have to be surrounded with '<...>'. For example, '<Control-Q>' and '<Alt-Up>' name events corresponding to normal or special keys with modifiers.

16.9.3.2 Mouse events
Button-1, Button-2, Button-3

The user pressed the left, middle, or right mouse-button. A two-button mouse produces only events Button-1 and Button-3, since it has no middle button.

B1-Motion, B2-Motion, B3-Motion

The user moved the mouse while pressing the left, middle, or right mouse button (there is no mouse event for mouse motion without pressing a button, except for Enter and Leave).

ButtonRelease-1, ButtonRelease-2, ButtonRelease-3

The user released the left, middle, or right mouse button.

Double-Button-1, Double-Button-2, Double-Button-3

The user double-clicked the left, middle, or right mouse button (such an action also generates Button-1, Button-2, or Button-3 before the double-click event).

Enter

The user moved the mouse so that the mouse entered the widget.

Leave

The user moved the mouse so that the mouse exited the widget.

16.9.4 Event-Related Methods

Each widget w supplies the following event-related methods.

bind

w.bind(event_name,callable[,'+'])

w.bind(event_name,callable) sets callable as the callback for event_name on w. w.bind(event_name,callable,'+') adds callable to the previous bindings for event_name on w.

bind_all

w.bind_all(event_name,callable[,'+'])

w.bind_all(event_name,callable) sets callable as the callback for event_name on any widget of the application, whatever widget w you call the method on. w.bind_all(event_name,callable,'+') adds callable to the previous bindings for event_name on any widget.

unbind

w.unbind(event_name)

Removes all callbacks for event_name on w.

unbind_all

w.unbind_all(event_name)

Removes all callbacks for event_name on any widget, previously set by calling method bind_all on any widget.

16.9.5 An Events Example

The following example shows how to detect key presses and mouse-button presses and releases using the bind_all method:

import Tkinter
from Tkinter import *

root = Tk(  )
prompt='Click any button, or press a key'
L = Label(root, text=prompt, width=len(prompt))
L.pack(  )

def key(event):
    if event.char=  =event.keysym:
        msg ='Normal Key %r' % event.char
    elif len(event.char)=  =1:
        msg ='Punctuation Key %r (%r)' % (event.keysym, event.char)
    else:
        msg ='Special Key %r' % event.keysym
    L.config(text=msg)
L.bind_all('<Key>', key)

def do_mouse(eventname):
    def mouse_binding(event):
        msg = 'Mouse event %s' % eventname
        L.config(text=msg)
    L.bind_all('<%s>'%eventname, mouse_binding)

for i in range(1,4):
    do_mouse('Button-%s'%i)
    do_mouse('ButtonRelease-%s'%i)
    do_mouse('Double-Button-%s'%i)

root.mainloop(  )

16.9.6 Other Callback-Related Methods

Each widget w supplies the following other callback-related methods.

after

w.after(ms,callable,*args)

Starts a timer that calls callable(*args) about ms milliseconds from now. Returns an ID that you can pass to after_cancel to cancel the timer. The timer is one-shot: for a function to be called periodically, the function itself must call after to install itself as a callback again.

after_cancel

w.after_cancel(id)

Cancels the timer identified by id.

after_idle

w.after_idle(callable,*args)

Registers a callback to callable(*args) to be performed when the event loop is idle (i.e., when all pending events have been processed).

The following example shows how to use after to implement a simple digital clock:

import Tkinter
import time

curtime = ''
clock = Tkinter.Label(  )
clock.pack(  )

def tick(  ):
    global curtime
    newtime = time.strftime('%H:%M:%S')
    if newtime != curtime:
        curtime = newtime
        clock.config(text=curtime)
    clock.after(200, tick)

tick(  )
clock.mainloop(  )

The kind of polling that method after lets you establish is an important Tkinter technique. Several Tkinter widgets have no callbacks to let you know about user actions on them, so if you want to track such actions in real-time, polling may be your only option. For example, here's how to use polling established with after to track a Listbox selection in real time:

import Tkinter

F1 = Tkinter.Frame(  )
s = Tkinter.Scrollbar(F1)
L = Tkinter.Listbox(F1)
s.pack(side=Tkinter.RIGHT, fill=Tkinter.Y)
L.pack(side=Tkinter.LEFT, fill=Tkinter.Y)
s['command'] = L.yview
L['yscrollcommand'] = s.set
for i in range(30): L.insert(Tkinter.END, str(i))
F1.pack(side=Tkinter.TOP)

F2 = Tkinter.Frame(  )
lab = Tkinter.Label(F2)
def poll(  ):
    lab.after(200, poll)
    sel = L.curselection(  )
    lab.config(text=str(sel))
lab.pack(  )
F2.pack(side=Tkinter.TOP)

poll(  )
Tkinter.mainloop(  )


    Part III: Python Library and Extension Modules