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 ObjectGeneral event callbacks must accept one argument event that is a Tkinter event object. Such an event object has several attributes describing the event:
16.9.2 Binding Callbacks to EventsTo 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 NamesFrequently used event names, which are almost all enclosed in angle brackets, fall into a few categories. 16.9.3.1 Keyboard events
16.9.3.2 Mouse events
16.9.4 Event-Related MethodsEach widget w supplies the following event-related methods.
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.
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.
Removes all callbacks for event_name on w.
Removes all callbacks for event_name on any widget, previously set by calling method bind_all on any widget. 16.9.5 An Events ExampleThe 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 MethodsEach widget w supplies the following other callback-related methods.
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.
Cancels the timer identified by id.
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( ) |