17.9. Tkinter Events
So far, we've seen only one kind of event handling: callbacks performed on callables set with the command= option of buttons and menu entries. Tkinter also lets you set callables to handle a variety of events.
Tkinter does not let you create custom events: you are limited to working with events predefined by Tkinter itself.
17.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 that describe 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
17.9.2. Binding Callbacks to Events
To bind a callback to an event in a widget w, call w.bind and describe 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 in tag_bind on page 430 and tag_bind on page 437) binds event callbacks to sets of items of a Canvas instance, or ranges within a Text instance.
17.9.3. Event Names
Common event names, almost all of which are enclosed in angle brackets, fall into a few categories.
17.9.3.1. Keyboard events
Key
The user clicked any key. The event object's attribute char tells you which key, for normal keys only. Attribute keysym is equal to char for letters and digits, the character's name for punctuation, and the key's name for special keys.
Special keys
Special keys have event names: F1, F2, and up are function keys; Left, Right, Up, and Down are arrows; Prior and Next are page-up and page-down; BackSpace, Delete, End, Home, Insert, Print, and Tab are the keys so labeled; Escape is the key labeled Esc; Return is the key labeled Enter; Caps_Lock, Num_Lock, and Scroll_Lock are lock-request keys; and Alt_L, Control_L, Shift_L are the modifier keys Alt, Ctrl, Shift (without distinction among multiple instances of such modifier keys in a keyboard). All of these event names are placed within angle brackets, like almost all event names.
Normal keys
Normal keys have event names without surrounding angle bracketsthe only event names that lack brackets. The event name of each normal key is the key's character, such as 'w', '1', or '+'. Exceptions are the Space key, with event name '<space>', and the key of the less-than character, with event name '<less>'.
Key names can be modified by the prefixes 'Alt-', 'Shift-', and 'Control-'. In this case, the event name is always surrounded with '<...>'; for example, '<Control-Q>' and '<Alt-Up>'.
17.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 (mouse motion without pressing a button can produce only 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.
17.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 all widgets. w.bind_all(event_name,callable,'+') adds callable to the previous bindings for event_name on all widgets.
| 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, as set by bind_all.
|
17.9.5. An Events Example
The following example detects key and mouse events with bind_all:
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):
L.config(text='Mouse event %s' % eventname)
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( )
17.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 to call callable(*args) ms milliseconds from now. Returns an ID that you can pass to after_cancel to cancel the timer. The timer is one-shot: to call a function periodically, the function itself must call after to install itself 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 uses 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( )
Method after is crucially important. Many widgets have no callbacks to let you know about user actions on them; to track such actions, polling is the only option. For example, here's how to poll 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, yscrollcommand=s.set)
s['command'] = L.yview 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( )
|