22.6 Writing your handlerThe sections above tell you how to describe what events you want to handle, and howto bind them. Now let us turn to the writing of the handler that will be called when theevent actually happens.The handler will be passed an Event object that describes what happened. The handlercan be either a function or a method. Here is the calling sequence <strong>for</strong> a regular function:And as a method:def handlerName ( event ):def handlerName ( self, event ):The members of the Event object passed to the handler are described below. Some ofthese members are always set, but some members are set only <strong>for</strong> certain types of events..char If the event was related to a KeyPress or KeyRelease <strong>for</strong> akey that produces a regular ASCII character, this string willbe set to that character. (For special keys like DELETE, see the.keysym member, below.).height If the event was a Configure, this member is set to thewidget’s new height in pixels..keysym For KeyPress or KeyRelease events involving a special key,this member is set to the key’s string name, e.g., "Prior"<strong>for</strong> the PAGEUP key. See the Key names table, above, <strong>for</strong> acomplete list of .keysym names..keysym_num For KeyPress or KeyRelease events, this is set to a numericversion of the .keysym field. For regular keys that producea single character, this field is set to the integer value of thekey’s ASCII code. For special keys, refer to the Key namestable, above..numIf the event was related to a mouse button, this member isset to the button number (1, 2, or 3)..time This member is set to an integer which has no absolute meaning,but is incremented every millisecond. This allows yourapplication to determine, <strong>for</strong> example, the length of timebetween two mouse clicks..widget Always set to the widget that caused the event. For example,if the event was a mouse click that happened on a canvas,this member will be the actual Canvas widget..width If the event was a Configure, this member is set to thewidget’s new width in pixels..x The x coordinate of the mouse at the time of the event, relativeto the upper left corner of the widget..y The y coordinate of the mouse at the time of the event, relativeto the upper left corner of the widget..x_root The x coordinate of the mouse at the time of the event, relativeto the upper left corner of the screen..y_root The y coordinate of the mouse at the time of the event, relativeto the upper left corner of the screen.Here’s an example of an event handler. Under Levels of binding, above, there is an exampleshowing how to bind mouse button 2 clicks on a canvas named self.canv to a handlercalled self.__drawOrangeBlob(). Here is that handler:New Mexico Tech Computer Center <strong>Tkinter</strong> <strong>reference</strong>: Events Page 82
def __drawOrangeBlob ( self, event ):"""Draws an orange blob in self.canv where the mouse is."""r = 5 # Blob radiusself.canv.create_oval ( event.x-r, event.y-r,event.x+r, event.y+r, fill="orange" )When this handler is called, the current mouse position is (event:x; event:y). The.create_oval() method draws a circle whose bounding box is square and centered onthat position and has sides of length 2*r.22.7 The extra arguments trickSometimes you would like to pass other arguments to a handler besides the event.Here is an example. Suppose your application has an array of ten checkbuttons whosewidgets are stored in a list self.cbList, indexed by the checkbutton number in therange [0, 9].Suppose further that you want to write one handler named .__cbHandler <strong>for</strong> events in all ten of these checkbuttons. The handler can get the actual Checkbuttonwidget that triggered it by referring to the .widget member of the Event object that getspassed in, but how does it find out that checkbutton’s index in the self.cbList array?It would be nice to write our handler with an extra argument <strong>for</strong> the checkbutton number,something like this:def __cbHandler ( self, event, cbNumber ):But event handlers are passed only one argument, the event. So we can’t use the functionabove because of a mismatch in the number of arguments.Fortunately, <strong>Python</strong>’s ability to provide default values <strong>for</strong> function arguments gives us away out. Have a look at this code:1def __createWidgets ( self ):2: : :3self.cbList = [] # Create the checkbutton list4<strong>for</strong> i in range(10):5cb = Checkbutton ( self, : : : )6self.cbList.append ( cb )7cb.grid( row=1, column=i )8def handler ( event, self=self, i=i ):9return self.__cbHandler ( event, i )10cb.bind ( "", handler )11: : :12def __cbHandler ( self, event, cbNumber ):Lines 8–9 define a new function handler that expects three arguments. The first argumentis the Event object passed to all event handlers, and the second and third arguments willbe set to their default values—the extra arguments we need to pass it.This technique can be extended to supply any number of additional arguments to handlers.New Mexico Tech Computer Center <strong>Tkinter</strong> <strong>reference</strong>: Events Page 83