Handling mouse and keyboard events
Being able to react to events is one of the most basic but important topics in GUI application development since it determines how users can interact with the program.
Pressing keys of the keyboard and clicking on items with the mouse are some common types of events, which are automatically handled in some Tkinter classes. For instance, this behavior is already implemented on the command
option of the Button
widget class, which invokes the specified callback function.
Some events can get triggered without user interaction, such as changing the input focus programmatically from one widget to another.
You can attach an event binding to a widget using the bind
method. The following example binds some mouse events to a Frame
instance:
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
frame = tk.Frame(self, bg="green",
height=100, width=100)
frame.bind("<Button-1>", self.print_event)
frame.bind("<Double-Button-1>", self.print_event)
frame.bind("<ButtonRelease-1>", self.print_event)
frame.bind("<B1-Motion>", self.print_event)
frame.bind("<Enter>", self.print_event)
frame.bind("<Leave>", self.print_event)
frame.pack(padx=50, pady=50)
def print_event(self, event):
position = "(x={}, y={})".format(event.x, event.y)
print(event.type, "event", position)
if __name__ == "__main__":
app = App()
app.mainloop()
All events are handled by the print_event()
method of our class, which prints the type of event and the position of the mouse in the console. You can try it out by clicking on the green frame with the mouse, and moving it around while it starts printing the event messages.
The following example contains an Entry widget with a couple of bindings; one for the event that gets triggered when the entry gets the focus, and another for all the key press events:
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
entry = tk.Entry(self)
entry.bind("<FocusIn>", self.print_type)
entry.bind("<Key>", self.print_key)
entry.pack(padx=20, pady=20)
def print_type(self, event):
print(event.type)
def print_key(self, event):
args = event.keysym, event.keycode, event.char
print("Symbol: {}, Code: {}, Char: {}".format(*args))
if __name__ == "__main__":
app = App()
app.mainloop()
The first message this program will output is the FocusIn
event when you set the focus on the Entry widget. If you try it out, you will see that it will also show the events of keys that do not correspond to non-printable characters, such as arrow keys or the return key.
The bind
method is defined in the widget
class and takes three arguments, an event sequence
, a callback
function, and an optional add
string:
widget.bind(sequence, callback, add='')
The sequence
string uses the <modifier-type-detail>
syntax.
In first place, modifiers are optional and allow you to specify additional combinations to the general type of the event:
Shift
: When the user presses the Shift keyAlt
: When the user presses the Alt keyControl
: When the user presses the Ctrl keyLock
: When the user presses the Shift lockDouble
: When the event happens twice in quick successionTriple
: When the event happens thrice in quick succession
Event types determine the general type of event:
ButtonPress
or Button
: Event generated when a mouse button is pressedButtonRelease
: Event generated when a mouse button is releasedEnter
: Event generated when you move the mouse over a widgetLeave
: Event generated when the mouse pointer leaves a widget
FocusIn
: Event generated when the widget gets the input focusFocusOut
: Event generated when the widget loses the input focusKeyPress
or Key
: Event generated when a key is pressedKeyRelease
: Event generated when a key is releasedMotion
: Event generated when the mouse is moved
The detail is also optional and serves to indicate the mouse button or key:
- For mouse events, 1 is the left button, 2 is the middle button, and 3 is the right button.
- For keyboard events, it is the key character. Special keys use the key symbol; some common examples are return, Tab, Esc, up, down, right, left, Backspace, and function keys (from F1 to F12).
The callback
function takes an event parameter. For mouse events, it has the following attributes:
x
and y
: Current mouse position in pixelsx_root
and y_root
: Same as x
and y
, but relative to the left-upper corner of the screennum
: Mouse button number
For keyboard events, it contains these attributes:
char
: Pressed character code as a stringkeysym
: Pressed key symbolkeycode
: Pressed key code
In both cases, the event has the widget
attribute, referencing the instance that generated the event, and type
, which specifies the event type.
Note
We strongly recommend that you define methods for the callback
functions since you will also have the reference to the class instance, and therefore you can easily access each of the widget
attributes.
Finally, the add
parameter can be ''
, to replace the callback
function if there was a previous binding, or '+'
to add the callback and preserve the old ones.
Apart from the event types described here, there are also other types that may be useful in some scenarios, such as the <Destroy>
event that is generated when a widget is destroyed or the <Configure>
event that is sent when the size or position of the widget changes.
You can check out the Tcl/Tk documentation for a complete list of event types at https://www.tcl.tk/man/tcl/TkCmd/bind.htm#M7.
- The Structuring a Tkinter application recipe