Binding an event

The basic format of an event binding is as follows:

widget.bind('<Event-String>', function_name)

Each widget has the ability to listen to the system for one of many event types. Each event type has a particular string defined within Tkinter to allow it to be mapped over to the Python interface. When the event passed via this string occurs, the function passed as the second parameter is executed. Note that the function is passed and not executed, just like the command argument of a Button widget.

When an application is written in an object-oriented manner, the function passed to the bind method is typically a regular class method. If the code is instead written procedurally, you will often see lambda functions used in order to access previously defined widgets. If you are not familiar with the way a lambda works, it is a good idea to familiarize yourself with that before continuing.

To try out some event bindings, get yourself another blank Python file and add the following code to it:

import tkinter as tk

win = tk.Tk()
can = tk.Canvas(win, width=300, height=300)
strvar = tk.StringVar()
lab = tk.Label(win, textvar=strvar)
strvar.set("Press a key")

Begin the file by creating a main window, Canvas, StringVar, and Label. The StringVar is set to a default value to make the Label show something when the window is first initialized.

Now we need a few functions to be called when our events are triggered, which are as follows:

def on_click(event=None):
can.create_oval((event.x - 5, event.y - 5, event.x + 5, event.y + 5),
fill="red")


def on_key_down(event=None):
strvar.set(event.keysym)


def on_ctrl_d(event=None):
top = tk.Toplevel(win)
top.geometry("200x200")
sv = tk.StringVar()
sv.set("Hover the mouse over me")
label = tk.Label(top, textvar=sv)
label.pack(expand=1, fill=tk.BOTH)

We have three functions which will be used to demonstrate three different events:

  • on_click: When the left mouse button is clicked, we will draw a small red dot in our Canvas.
  • on_key_down: When a key on the keyboard is pressed, we will display it using our Label
  • on_ctrl_d: When the control key is held and the d key is pressed, we will display a second window. There will be more to this function added shortly.

Each function takes a single argument—event. This is a special object that Tkinter will pass to a function which has been bound via the bind method. This object contains information regarding the event which took place, and has different properties based on the type of event which was captured.

When this object is spawned from a mouse event, for instance, it will contain the coordinates of where on the widget the user has clicked. These are stored in its x and y properties. We use these x and y properties in order to create the bounding box for our dot with our on_click function. This is how we know the dot will appear underneath where the user has clicked.

During a keyboard event, the event object will hold information about what key has been pressed. There are multiple properties holding various different bits of data, but the human-readable representation of the key will be stored in its keysym property. We set the value of the StringVar referenced by our Label to this string, allowing us to show the user what key has been pressed.

Now that we have the functions to be bound, all that's left is to do the binding. Add this to the following functions:

can.bind('<Button-1>', on_click)
win.bind('<KeyPress>', on_key_down)
win.bind('<Control-d>', on_ctrl_d)

can.pack()
lab.pack(side=tk.BOTTOM)

win.mainloop()

To bind to the left-click of the mouse, the special string is <Button-1>. Since the Canvas is what will draw our dots, we call the bind method on its instance.

On each keyboard's key press, both the <KeyPress> and <KeyRelease> events will trigger. The first occurs when the key is pushed in and the latter when the key is released.

In order to bind to a modifier key (such as control) and a regular key, we use the modifier key first, joined to the regular key with a hyphen. To bind to Ctrl and D, the string will be <Control-d>.  Similarly, holding the shift key and pressing the s key would be <Shift-s>.

Our widgets are packed and our window is displayed.

Save and run this code, then try clicking over the canvas. You should be spawning small red dots each time you click.

Then try pressing keys on the keyboard and observe the text appearing at the bottom of the window. You can use this feature any time you are unsure of what the special name is for a key you are trying to bind an event to. 

If you hold Ctrl and press the letter D, you should see a second window appear. Although it tells you to hover the mouse over it, nothing happens when you do. Let's fix this. Add the following to the on_ctrl_d function:

label.bind("<Enter>", lambda e, sv=sv: sv.set("Hello mouse!"))
label.bind("<Leave>", lambda e, sv=sv: sv.set("Goodbye mouse!"))

At first glance, you may assume the <Enter> event is the Enter key, but it is actually used to detect the mouse cursor entering the boundaries of a widget.

Conversely, the <Leave> binding detects the mouse leaving the bounds of a widget.

Using these two events, we can detect when the mouse is hovering over the Label and change its text. A lambda function is used to change the text of our StringVar variable depending on the position of the mouse.

Run this updated version of the code, press Ctrl + D, then move the mouse cursor in and out of the newly spawned window. You should see the text change as you do so.

Now we know how to add behavior to certain events. We also saw in our text editor application that some widgets will come with default events already programmed. These are changeable, too, but require an extra step.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset