Book Image

Tkinter GUI Application Development Cookbook

By : Alejandro Rodas de Paz
Book Image

Tkinter GUI Application Development Cookbook

By: Alejandro Rodas de Paz

Overview of this book

As one of the more versatile programming languages, Python is well-known for its batteries-included philosophy, which includes a rich set of modules in its standard library; Tkinter is the library included for building desktop applications. Due to this, Tkinter is a common choice for rapid GUI development, and more complex applications can benefit from the full capabilities of this library. This book covers all of your Tkinter and Python GUI development problems and solutions. Tkinter GUI Application Development Cookbook starts with an overview of Tkinter classes and at the same time provides recipes for basic topics, such as layout patterns and event handling. Next, we cover how to develop common GUI patterns, such as entering and saving data, navigating through menus and dialogs, and performing long-running actions in the background.You can then make your apps leverage network resources effectively and perform graphical operations on a canvas and related tasks such as detecting collisions between items. Finally, this book covers using themed widgets, an extension of Tk widgets that have a more native look and feel. Finally, this book covers using the canvas and themed widgets. By the end of the book, you will have an in-depth knowledge of Tkinter classes, and will know how to use them to build efficient and rich GUI applications.
Table of Contents (10 chapters)

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.

How to do it...

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.

How it works...

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 key
  • Alt: When the user presses the Alt key
  • Control: When the user presses the Ctrl key
  • Lock: When the user presses the Shift lock
  • Double: When the event happens twice in quick succession
  • Triple: 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 pressed
  • ButtonRelease: Event generated when a mouse button is released
  • Enter: Event generated when you move the mouse over a widget
  • Leave: Event generated when the mouse pointer leaves a widget
  • FocusIn: Event generated when the widget gets the input focus
  • FocusOut: Event generated when the widget loses the input focus
  • KeyPress or Key: Event generated when a key is pressed
  • KeyRelease: Event generated when a key is released
  • Motion: 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 pixels
  • x_root and y_root: Same as x and y, but relative to the left-upper corner of the screen
  • num: Mouse button number

For keyboard events, it contains these attributes:

  • char: Pressed character code as a string
  • keysym: Pressed key symbol
  • keycode: 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.

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.

There's more...

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.

See also

  • The Structuring a Tkinter application recipe