Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Tkinter GUI Application Development Blueprints
Tkinter GUI Application Development Blueprints

Tkinter GUI Application Development Blueprints: Master GUI programming in Tkinter as you design, implement, and deliver 10 real-world applications

eBook
$9.99 $39.99
Paperback
$48.99
Subscription
Free Trial
Renews at $19.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

Tkinter GUI Application Development Blueprints

Chapter 1. Meet Tkinter

Welcome to the exciting world of GUI programming with Tkinter. This chapter aims at getting you acquainted with Tkinter, the built-in graphical user interface (GUI) library for all standard Python distributions.

Tkinter (pronounced tea-kay-inter) is the Python interface to Tk, the GUI toolkit for Tcl/Tk.

Tcl (short for Tool Command Language and pronounced as tickle) is a popular scripting language in the domains of embedded applications, testing, prototyping, and GUI development. On the other hand, Tk is an open source, multi-platform widget toolkit that is used by many different languages to build GUI programs.

The Tkinter interface is implemented as a Python module—Tkinter.py in Python 2.x versions and tkinter/__init__.py in Python 3.x versions. If you look at the source code, Tkinter is just a wrapper around a C extension that uses the Tcl/Tk libraries.

Tkinter is suitable for application to a wide variety of areas, ranging from small desktop applications to use in scientific modeling and research endeavors across various disciplines.

When a person learning Python needs to graduate to GUI programming, Tkinter seems to be the easiest and fastest way to get the work done.

Tkinter is a great tool for the programming of GUI applications in Python.

The features that make Tkinter a great choice for GUI programming include the following:

  • It is simple to learn (simpler than any other GUI package for Python)
  • Relatively little code can produce powerful GUI applications
  • Layered design ensures that it is easy to grasp
  • It is portable across all operating systems
  • It is easily accessible, as it comes pre-installed with the standard Python distribution

None of the other Python GUI toolkits have all of these features at the same time.

Objectives of this chapter

The purpose of this chapter is to make you comfortable with Tkinter. It aims at introducing you to the various components of GUI programming with Tkinter.

By the end of this chapter, you will have developed several partly-functional dummy applications, such as the one shown in the following screenshot:

Objectives of this chapter

We believe that the concepts that you will develop here will enable you to apply and develop GUI applications in your area of interest.

The key aspects that we want you to learn from this chapter include the following:

  • Understanding the concept of a root window and a main loop
  • Understanding widgets—the building blocks of programs
  • Getting acquainted with a list of available widgets
  • Developing layouts by using different geometry managers
  • Applying events and callbacks to make a program functional
  • Styling widgets by using styling options and configuring the root widget

Installing Python and Tkinter

To work on the projects in this chapter, you must have a working copy of Python 3.4.0 installed on your computer.

The Python download package and instructions for downloading for different platforms are available at https://www.python.org/downloads/release/python-340/.

The installer binaries for Mac OS X and the Windows platform are available at the aforementioned link. Python 3.4 is installed by default on Ubuntu 14.04. Unfortunately, Ubuntu 14.04 does not ship with Tkinter. You have to install it manually. Other Linux users can also install the Python Interpreter (v3.4) package from the official repository or build it directly from the source link provided in the aforementioned link.

We will develop our application on the Ubuntu platform. However, since Tkinter is cross-platform, you can follow along with the instructions in this book on Windows, Mac, or any other Linux distribution, without making any modifications to the code.

After installing Python, open the Python 3.4 interactive shell and type in the following command:

>>> import tkinter

This shell command should be executed without an error.

If there are no error messages, the Tkinter module is installed on your Python distribution. When working with examples from this book, we do not support any Python version except for Python 3.4.0, which comes bundled with Tkinter Tcl/Tk Version 8.6. However, most of the examples should work out-of-the-box on other minor Python 3 versions.

To check whether you have the correct Tkinter version on your Python installation, type the following commands in your IDLE or interactive shell:

>>> import tkinter
>>> tkinter._test()

This should make a window pop up. The first line in the window reads This is Tcl/Tk version 8.6. Make sure that it is not 8.5 or any earlier version, as Version 8.6 is a vast improvement over its previous versions.

You are ready to code Tkinter GUI applications if your version test confirms it as Tcl/Tk version 8.6.

Let's get started!

Importing Tkinter

This section describes the different styles of importing Tkinter modules. In the preceding example, we imported Tkinter by using the following command:

from tkinter import *

This method of importing eases the handling of methods defined in the module. That is to say, you can simply access the methods directly. Generally, it is considered bad practice to import all (*) the methods of a module like we did here. This is so because this style of importing leads to memory flooding, namespace confusion, and difficulty in bug tracking and/or reviewing code. Importing into the global namespace can also lead to an accidental overwriting of methods from other libraries in the global namespace.

There are several ways to import Tkinter in which this overlapping can be avoided, with a common way being the following one:

import tkinter

This style of importing does not pollute the namespace with a list of all the methods defined within Tkinter. However, every method within Tkinter will now have to be called by using the tkinter.some_method format instead of directly calling the method.

Another commonly used import style is as follows:

import tkinter as tk

Here too, you do not pollute the current namespace with all the Tkinter methods. Now, you can access methods such as tk.some_method. The tk alias is convenient and easy to type. It is commonly used by many developers to import Tkinter.

GUI programming – the big picture

As a GUI programmer, you will generally be responsible for deciding the following three aspects of your program:

  • Which components should appear on the screen? This involves choosing the components that make the user interface. Typical components include things such as buttons, entry fields, checkboxes, radio buttons, scroll bars, and the like. In Tkinter, the components that you add to your GUI are called widgets. Widgets (short for window gadgets) are the graphical components that make up your application's frontend.
  • Where should the components go? This includes deciding the position and the structural layout of various components. In Tkinter, this is referred to as geometry management.
  • How do components interact and behave? This involves adding functionality to each component. Each component or widget does some work. For example, a button, when clicked on, does something in response. A scrollbar handles scrolling, and checkboxes and radio buttons enable users to make some choices. In Tkinter, the functionality of various widgets is managed by the command binding or the event binding using callback functions.

The following figure shows the three components of GUI programming:

GUI programming – the big picture

Let's delve deeper into each of these three components in the context of Tkinter.

The root window – your drawing board

GUI programming is an art, and like all art, you need a drawing board to capture your ideas. The drawing board that you will use is called the root window. Our first goal is to get the root window ready.

The following screenshot depicts the root window that we are going to create:

The root window – your drawing board

Drawing the root window is easy. You just need the following three lines of code:

from tkinter import *
root = Tk()
root.mainloop()

Save this with the .py file extension or check out the 1.01.py code. Open it in the IDLE window and run the program from the Run menu (F5 in IDLE). Running this program should generate a blank root window, as shown in the preceding screenshot. This window is equipped with the functional minimize, maximize, and close buttons, and a blank frame.

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

The following is a description of the preceding code:

  • The first line imported all (*) the classes, attributes, and methods of Tkinter into the current workspace.
  • The second line created an instance of the tkinter.Tk class. This created what is called the "root" window, which is shown in the preceding screenshot. According to the conventions, the root window in Tkinter is usually called "root", but you are free to call it by any other name.
  • The third line executed the mainloop (that is, the event loop) method of the root object. The mainloop method is what keeps the root window visible. If you remove the third line, the window created in line 2 will disappear immediately as soon as the script stops running. This will happen so fast that you will not even see the window appearing on your screen. Keeping the mainloop method running also lets you keep the program running until you press the close button, which exits the main loop.
  • Tkinter also exposed the mainloop method as tkinter.mainloop(). So, you can even call mainloop() directly instead of calling root.mainloop().

Congratulations! You have completed your first objective, which was to draw the root window. You have now prepared your drawing board (root window). Now, get ready to paint it with your imagination!

Note

Commit the three lines of code (shown in code 1.01.py) to memory. These three lines generate your root window, which will accommodate all the other graphical components. These lines form the skeleton of any GUI application that you will develop in Tkinter. The entire code that will make your GUI application functional will go between line 2 (new object creation) and line 3 (mainloop) of this code.

Widgets – the building blocks of GUI programs

Now that we have our top level or the root window ready, it is time to think over a question—which components should appear in the window? In Tkinter jargon, these components are called widgets.

The syntax that is used to add a widget is as follows:

my_widget = Widget-name (its container window, ** its configuration options)

In the following example (1.02.py), we will add two widgets, a label, and a button to the root frame. Note how all the widgets are added between the skeleton code that we defined in the first example:

from tkinter import *
root = Tk()
label = Label(root, text="I am a label widget")
button = Button(root, text="I am a button")
label.pack()
button.pack()
root.mainloop()

The following is a description of the preceding code:

  • This code added a new instance named label for the Label widget. The first parameter defined root as its parent or container. The second parameter configured its text option as I am a label widget.
  • Similarly, we defined an instance of a Button widget. This is also bound to the root window as its parent.
  • We used the pack() method, which is essentially required to position the label and button widgets within the window. We will discuss the pack() method and several other related concepts when exploring the geometry management task. However, you must note that some sort of geometry specification is essential for the widgets to be displayed within the top-level window.

Running the preceding code will generate a window with a label and a button widget, as shown in the following screenshot:

Widgets – the building blocks of GUI programs

Some important widget features

Note the following few important features that are common to all widgets:

  • All widgets are actually objects derived from their respective widget classes. So, a statement such as button = Button(its_parent) actually creates a button instance from the Button class.
  • Each widget has a set of options that decides its behavior and appearance. This includes attributes such as text labels, colors, and font size. For example, the Button widget has attributes to manage its label, control its size, change its foreground and background colors, change the size of the border, and so on.
  • To set these attributes, you can set the values directly at the time of creating the widget, as demonstrated in the preceding example. Alternatively, you can later set or change the options of the widget by using the .config() or .configure() method. Note that the .config() or .configure() methods are interchangeable and provide the same functionality. In fact, the .config() method is simply an alias of the .configure() method.

Ways to create widgets

There are two ways to create widgets in Tkinter.

The first way involves creating a widget in one line and then adding the pack() method (or other geometry managers) in the next line, as follows:

my_label = Label(root, text="I am a label widget")
my_label.pack()

Alternatively, you can write both the lines together, as follows:1

Label(root, text="I am a label widget").pack()

You can either save a reference to the widget created (my_label, as in the first example), or create a widget without keeping any reference to it (as demonstrated in the second example).

You should ideally keep a reference to the widget in case the widget has to be accessed later on in the program. For instance, this is useful in case you need to call one of its internal methods or for its content modification. If the widget state is supposed to remain static after its creation, you need not keep a reference to the widget.

Tip

Note that calls to pack() (or other geometry managers) always return None. So, consider a situation where you create a widget, save a reference to it, and add a geometry manager (say, pack()) on the same line, as follows:

my_label = Label(...).pack()

In this case, you are actually not creating a reference to the widget. Instead, you are creating a None type object for the my_label variable.

So, when you later try to modify the widget through the reference, you get an error because you are actually trying to work on a None type object.

If you need a reference to a widget, you must create it on one line and then specify its geometry (like pack()) on the second line, as follows:

my_label = Label(...)
my_label.pack()

This is one of the most common errors committed by beginners.

Getting to know the core Tkinter widgets

Now, you will get to know all the core Tkinter widgets. You have already seen two of them in the previous example—the Label and Button widgets. Now, let's see all the other core Tkinter widgets.

Tkinter includes 21 core widgets, which are as follows:

Toplevel widget

Label widget

Button widget

Canvas widget

Checkbutton widget

Entry widget

Frame widget

LabelFrame widget

Listbox widget

Menu widget

Menubutton widget

Message widget

OptionMenu widget

PanedWindow widget

Radiobutton widget

Scale widget

Scrollbar widget

Spinbox widget

Text widget

Bitmap Class widget

Image Class widget

Let's write a program to display all of these widgets in the root window.

Adding widgets to a parent window

The format used to add widgets is the same as the one that we discussed in the previous task. To give you an idea about how it's done, here's some sample code that adds some common widgets:

Label(parent, text="Enter your Password:")
Button(parent, text="Search")
Checkbutton(parent, text="Remember Me", variable=v, value=True)
Entry(parent, width=30)
Radiobutton(parent, text="Male", variable=v, value=1)
Radiobutton(parent, text="Female", variable=v, value=2)
OptionMenu(parent, var, "Select Country", "USA", "UK", "India", "Others")
Scrollbar(parent, orient=VERTICAL, command= text.yview)

Can you spot the pattern that is common to each widget? Can you spot the differences?

As a reminder, the syntax for adding a widget is as follows:

Widget-name(its_parent, **its_configuration_options)

Using the same pattern, let's add all the 21 core Tkinter widgets into a dummy application (the 1.03.py code). We do not produce the entire code here. A summarized code description for 1.03.py is as follows:

  • We create a top-level window and a main loop, as shown in the earlier examples.
  • We add a Frame widget and name it menu_bar. Note that Frame widgets are just holder widgets that hold other widgets. Frame widgets are great for grouping widgets together. The syntax for adding a frame is the same as that of all the other widgets:
    frame = Frame(root)
    frame.pack()
  • Keeping the menu_bar frame as the container, we add two widgets to it:
    • Menubutton
    • Menu
  • We create another Frame widget and name it frame. Keeping frame as the container/parent widget, we add the following seven widgets to it:
    • Label
    • Entry
    • Button
    • Checkbutton
    • Radiobutton
    • OptionMenu
    • Bitmap Class
  • We then proceed to create another Frame widget. We add six more widgets to the frame:
    • Image Class
    • Listbox
    • Spinbox
    • Scale
    • LabelFrame
    • Message
  • We then create another Frame widget. We add two more widgets to the frame:
    • Text
    • Scrollbar
  • We create another Frame widget and add two more widgets to it:
    • Canvas
    • PanedWindow

All of these widgets constitute the 21 core widgets of Tkinter.

Now that you have had a glimpse of all the widgets, let's discuss how to specify the location of these widgets using geometry managers.

The Tkinter geometry manager

You may recall that we used the pack() method to add widgets to the dummy application that we developed in the previous section. The pack() method is an example of geometry management in Tkinter.

The pack() method is not the only way of managing the geometry in your interface.

In fact, there are three geometry managers in Tkinter that let you specify the position of widgets inside a top-level or parent window.

The three geometry managers are as follows:

  • pack: This is the one that we have used so far. It is simple to use for simpler layouts, but it may get very complex for slightly complex layouts.
  • grid: This is the most commonly used geometry manager that provides a table-like layout of management features for easy layout management.
  • place: This is the least popular, but it provides the best control for the absolute positioning of widgets.

Now, let's have a look at some examples of all the three geometry managers in action.

The pack geometry manager

The pack manager can be a bit tricky to explain in words, and it can best be understood by playing with the code base. Fredrik Lundh, the author of Tkinter, asks us to imagine the root as an elastic sheet with a small opening at the center. The pack geometry manager makes a hole in the elastic sheet that is just large enough to hold the widget. The widget is placed along a given inner edge of the gap (the default is the top edge). It then repeats the process till all the widgets are accommodated. Finally, when all the widgets have been packed in the elastic sheet, the geometry manager calculates the bounding box for all the widgets. It then makes the parent widget large enough to hold all the child widgets.

When packing the child widgets, the pack manager distinguishes between the following three kinds of space:

  • The unclaimed space
  • The claimed but unused space
  • The claimed and used space

The most commonly used options in pack include the following:

  • side: LEFT, TOP, RIGHT, and BOTTOM (these decide the alignment of the widget)
  • fill: X, Y, BOTH, and NONE (these decide whether the widget can grow in size)
  • expand: Boolean values such as tkinter.YES/tkinter.NO, 1/0, True/False
  • anchor: NW, N, NE, E, SE, S, SW, W, and CENTER (corresponding to the cardinal directions)
  • Internal padding (ipadx and ipady) for the padding inside widgets and external padding (padx and pady), which all default to a value of zero

Let's take a look at a demo code that illustrates some of the pack features.

Two of the most commonly used pack options are fill and expand.

Here's the code snippet (code 1.04.py) that will generate a GUI like the one shown in following screenshot:

The pack geometry manager

The following is the code (1.04.py) that generates the preceding GUI:

from tkinter import *
root = Tk()

frame = Frame(root)
# demo of side and fill options
Label(frame, text="Pack Demo of side and fill").pack()
Button(frame, text="A").pack(side=LEFT, fill=Y)
Button(frame, text="B").pack(side=TOP, fill=X)
Button(frame, text="C").pack(side=RIGHT, fill=NONE)
Button(frame, text="D").pack(side=TOP, fill=BOTH)
frame.pack()
# note the top frame does not expand nor does it fill in

# X or Y directions
# demo of expand options - best understood by expanding the root widget and seeing the effect on all the three buttons below.
Label (root, text="Pack Demo of expand").pack()
Button(root, text="I do not expand").pack()
Button(root, text="I do not fill x but I expand").pack(expand = 1)
Button(root, text="I fill x and expand").pack(fill=X, expand=1)
root.mainloop()

The following is a description of the preceding code:

  • When you insert the A button in the root frame, it captures the leftmost area of the frame, expands, and fills the Y dimension. Because the fill option is specified as fill=Y, it claims all the area that it wants and fills the Y dimension of its frame container frame.
  • Because frame is itself packed with a plain pack() method with no mention of a pack option, it takes the minimum space required to accommodate all of its child widgets.
  • If you increase the size of the root window by pulling it down or sideways, you will see that the all the buttons within frame do not fill or expand with the root window.
  • The positioning of the B, C, and D buttons occurs on the basis of the side and fill options specified for each of them.
  • The next three buttons (after B, C, and D) demonstrate the use of the expand option. A value of expand=1 means that the button moves its place on resizing the window. Buttons with no explicit expand options stay at their place and do not respond to changes in the size of their parent container (the root window in this case).
  • The best way to study this piece of code would be to resize the root window to see the effect that it has on various buttons.
  • The anchor attribute (not used in the preceding code) provides a means to position a widget relative to a reference point. If the anchor attribute is not specified, the pack manager places the widget at the center of the available space or the packing box. The other options that are allowed include the four cardinal directions (N, S, E, and W) and a combination of any two directions. Therefore, valid values for the anchor attribute are CENTER (the default value), N, S, E, W, NW, NE, SW, and SE.

Note

The value for most of the Tkinter geometry manager attributes can either be specified in capital letters without quotes (such as side=TOP, anchor=SE) or in small letters within quotes (such as side='top', anchor='se').

We will use the pack geometry manager in some of our projects. Therefore, it will be worthwhile to get acquainted with pack and its options.

The pack manager is ideally suited for the following two kinds of situation:

  • Placing widgets in a top-down manner
  • Placing widgets side by side

Code 1.05.py shows an example of both of these scenarios:

parent = Frame(root)
# placing widgets top-down
Button(parent, text='ALL IS WELL').pack(fill=X)
Button(parent, text='BACK TO BASICS').pack(fill=X)
Button(parent, text='CATCH ME IF U CAN').pack(fill=X)
# placing widgets side by side
Button(parent, text='LEFT').pack(side=LEFT)
Button(parent, text='CENTER').pack(side=LEFT)
Button(parent, text='RIGHT').pack(side=LEFT)
parent.pack()

The preceding code produces a GUI, as shown in the following screenshot:

The pack geometry manager

For a complete pack reference, type the following command in the Python shell:

>>> import tkinter
>>> help(tkinter.Pack)

Tip

Where should you use the pack() geometry manager ?

Using the pack manager is somewhat complicated as compared to the grid method, which will be discussed next, but it is a great choice in situations such as the following ones:

  • Having a widget fill the complete container frame.
  • Placing several widgets on top of each other or side by side (as shown in the preceding screenshot). See code 1.05.py.

Although you can create complicated layouts by nesting widgets in multiple frames, you will find the grid geometry manager more suitable for most of the complex layouts.

The grid geometry manager

The grid geometry manager is easy to understand and perhaps the most useful geometry manager in Tkinter. The central idea of the grid geometry manager is to organize the container frame into a two-dimensional table, which is divided into a number of rows and columns. Each cell in the table can then be targeted to hold a widget. In this context, a cell is an intersection of imaginary rows and columns. Note that in the grid method, each cell can hold only one widget. However, widgets can be made to span multiple cells.

Within each cell, you can further align the position of the widget using the sticky option. The sticky option decides how the widget is expanded. If its container cell is larger than the size of the widget that it contains, the sticky option can be specified using one or more of the N, S, E, and W options or the NW, NE, SW, and SE options.

Not specifying stickiness defaults to stickiness to the center of the widget in the cell.

Let's have a look at a demo code that illustrates some of the features of the grid geometry manager. The code in 1.06.py generates a GUI, as shown in the following screenshot:

The grid geometry manager

The following is the code (1.06.py) that generates the preceding GUI:

from tkinter import *
root = Tk()
Label(root, text="Username").grid(row=0, sticky=W)
Label(root, text="Password").grid(row=1, sticky=W)
Entry(root).grid(row=0, column=1, sticky=E)
Entry(root).grid(row=1, column=1, sticky=E)
Button(root, text="Login").grid(row=2, column=1, sticky=E)
root.mainloop()

The following is a description of the preceding code:

  • Take a look at the grid position defined in terms of the row and column positions for an imaginary grid table spanning the entire frame. See how the use of sticky=W on both the labels makes them stick on the left-hand side, thus resulting in a clean layout.
  • The width of each column (or the height of each row) is automatically decided by the height or width of the widgets in the cell. Therefore, you need not worry about specifying the row or column width as equal. You can specify the width for widgets if you need that extra bit of control.
  • You can use the sticky=NSEW argument to make the widget expandable and fill the entire cell of the grid.

In a more complex scenario, your widgets may span across multiple cells in the grid. To make a grid to span multiple cells, the grid method offers handy options such as rowspan and columnspan.

Furthermore, you may often need to provide some padding between cells in the grid. The grid manager provides the padx and pady options to provide padding that needs to be placed around a widget.

Similarly, the ipadx and ipady options are used for internal padding. These options add padding within the widget itself. The default value of an external and internal padding is 0.

Let's have a look at an example of the grid manager, where we use most of the common arguments to the grid method, such as row, column, padx, pady, rowspan, and columnspan.

Code 1.07.py produces a GUI, as shown in the following screenshot, to demonstrate how to use the grid geometry manager options:

The grid geometry manager

The following is the code (1.07.py) that generates the preceding GUI:

from tkinter import *
parent = Tk()
parent.title('Find & Replace')

Label(parent, text="Find:").grid(row=0, column=0, sticky='e')
Entry(parent, width=60).grid(row=0, column=1, padx=2, pady=2, sticky='we', columnspan=9)

Label(parent, text="Replace:").grid(row=1, column=0, sticky='e')
Entry(parent).grid(row=1, column=1, padx=2, pady=2, sticky='we', columnspan=9)

Button(parent, text="Find").grid(
  row=0, column=10, sticky='e' + 'w', padx=2, pady=2)
Button(parent, text="Find All").grid(
  row=1, column=10, sticky='e' + 'w', padx=2)
Button(parent, text="Replace").grid(row=2, column=10, sticky='e' + 'w', padx=2)
Button(parent, text="Replace All").grid(
  row=3, column=10, sticky='e' + 'w', padx=2)
Checkbutton(parent, text='Match whole word only').grid(
  row=2, column=1, columnspan=4, sticky='w')
Checkbutton(parent, text='Match Case').grid(
  row=3, column=1, columnspan=4, sticky='w')
Checkbutton(parent, text='Wrap around').grid(
  row=4, column=1, columnspan=4, sticky='w')
Label(parent, text="Direction:").grid(row=2, column=6, sticky='w')
Radiobutton(parent, text='Up', value=1).grid(
  row=3, column=6, columnspan=6, sticky='w')
Radiobutton(parent, text='Down', value=2).grid(
  row=3, column=7, columnspan=2, sticky='e')
parent.mainloop()

Note how just 14 lines of the core grid manager code generate a complex layout such as the one shown in the preceding screenshot. On the contrary, developing this with the pack manager would have been much more tedious.

Another grid option that you can sometimes use is the widget.grid_forget() method. This method can be used to hide a widget from the screen. When you use this option, the widget still exists at its former location, but it becomes invisible. The hidden widget may be made visible again, but the grid options that you had originally assigned to the widget will be lost.

Similarly, there is a widget.grid_remove() method that removes the widget, except that in this case, when you make the widget visible again, all of its grid options will be restored.

For a complete grid reference, type the following command in the Python shell:

>>> import tkinter
>>> help(tkinter.Grid)

Tip

Where should you use the grid geometry manager?

The grid manager is a great tool for the development of complex layouts. Complex structures can be easily achieved by breaking the container widget into grids of rows and columns and then placing the widgets in grids where they are wanted. It is also commonly used to develop different kinds of dialog boxes.

Now, we will delve into configuring a grid's column and row sizes.

Different widgets have different heights and widths. So, when you specify the position of a widget in terms of rows and columns, the cell automatically expands to accommodate the widget.

Normally, the height of all the grid rows is automatically adjusted to be the height of its tallest cell. Similarly, the width of all the grid columns is adjusted to be equal to the width of the widest widget cell.

If you then want a smaller widget to fill a larger cell or to stay at any one side of the cell, you can use the sticky attribute on the widget to control this aspect.

However, you can override this automatic sizing of columns and rows by using the following code:

w.columnconfigure(n, option=value, ...)  AND
w.rowconfigure(N, option=value, ...)

Use these to configure the options for a given widget, w, in either the nth column or the nth row, specifying values for the options, minsize, pad, and weight. Note that the numbering of rows begins from 0 and not 1.

The options available are as follows:

Options

Description

minsize

This is the minimum size of a column or row in pixels. If there is no widget in a given column or row, the cell does not appear in spite of this minsize specification.

pad

This is the external padding in pixels that will be added to the specified column or row over the size of the largest cell.

weight

This specifies the relative weight of a row or column and then distributes the extra space. This enables making the row or column stretchable.

For example, the following code distributes two-fifths of the extra space to the first column and three-fifths to the second column:

w.columnconfigure(0, weight=2)
w.columnconfigure(1, weight=3)

The columnconfigure() and rowconfigure() methods are often used to implement the dynamic resizing of widgets, especially on resizing the root window.

Note

You cannot use the grid and pack methods together in the same container window. If you try doing that, your program will raise a _tkinter.TclError error.

The place geometry manager

The place geometry manager is the most rarely used geometry manager in Tkinter. Nevertheless, it has its uses in that it lets you precisely position widgets within its parent frame by using the (x,y) coordinate system.

The place manager can be accessed by using the place() method on all the standard widgets.

The important options for place geometry include the following:

  • Absolute positioning (specified in terms of x=N or y=N)
  • Relative positioning (the key options include relx, rely, relwidth, and relheight)

The other options that are commonly used with place include width and anchor (the default is NW). Refer to the code in 1.08.py for a demonstration of the common place options:

from tkinter import *
root = Tk()
# Absolute positioning
Button(root, text="Absolute Placement").place(x=20, y=10)
# Relative positioning
Button(root, text="Relative").place( relx=0.8, rely=0.2, relwidth=0.5, width=10, anchor=NE)
root.mainloop()

You may not see much of a difference between the absolute and relative positions simply by looking at the code or the window frame. However, if you try resizing the window, you will observe that the button placed does not change its coordinates, while the relative button changes its coordinates and size to accommodate the new size of the root window.

The place geometry manager

For a complete place reference, type the following command in the Python shell:

>>> import tkinter
>>> help(tkinter.Place)

Tip

When should you use the place manager?

The place manager is useful in situations where you have to implement the custom geometry managers, where the widget placement is decided by the end user.

While the pack and grid managers cannot be used together in the same frame, the place manager can be used with any geometry manager within the same container frame.

The place manager is rarely used because, if you use it, you have to worry about the exact coordinates. If you make a minor change to a widget, it is very likely that you will have to change the X-Y values for other widgets as well, which can be very cumbersome.

We will not use the place manager in our projects. However, knowing that options for coordinate-based placement exist can be helpful in certain situations.

This concludes our discussion on geometry management in Tkinter.

In this section, you had a look at how to implement the pack, grid, and place geometry managers. You also understood the strengths and weaknesses of each geometry manager.

You learned that pack is suitable for a simple side-wise or top-down widget placement. You also learned that the grid manager is best suited for the handling of complex layouts. You saw examples of the place geometry manager and explored the reasons behind why it is rarely used.

You should now be able to plan and execute different layouts for your programs using these Tkinter geometry managers.

Events and callbacks – adding life to programs

Now that you have learned how to add widgets to a screen and position them where you want, let's turn our attention to the third component of GUI programming.

This addresses the question of how to make widgets functional.

Making widgets functional involves making them responsive to events such as the pressing of buttons, the pressing of keys on a keyboard, mouse clicks, and the like. This requires associating callbacks with specific events.

Callbacks are normally associated with specific widget events using the command binding rules, which is discussed in the following section.

Command binding

The simplest way to add functionality to a button is called command binding, whereby a callback function is mentioned in the form of command = some_callback in the widget option. Note that the command option is available only for a few selected widgets.

Take a look at the following sample code:

def my_callback ():
  # do something when button is clicked

After defining the above callback we can connect it to, say, a button with the command option referring to the callback, as follows:

  Button(root, text="Click me", command=my_callback)

A callback is a function memory reference (my_callback in the preceding example) that is called by another function (which is Button in the preceding example), which takes the first function as a parameter. Put simply, a callback is a function that you provide to another function so that it can call it.

Note that my_callback is passed without parentheses () from within the widget command option, because when the callback functions are set, it is necessary to pass a reference to a function rather than actually call it.

If you add parentheses () like you do for any normal function, it would be called as soon as the program runs. In contrast, the callback is called only when an event occurs (the pressing of a button in this case).

Passing arguments to callbacks

If a callback does not take any argument, it can be handled with a simple function, such as the one shown in the preceding code. However, if a callback needs to take arguments, we can use the lambda function, as shown in the following code snippet:

def my_callback (argument)
  #do something with argument

Then, somewhere else in the code, we define a button with a command callback that takes some arguments, as follows:

  Button(root,text="Click", command=lambda: my_callback ('some argument'))

Python borrows syntax from functional programming called the lambda function. The lambda function lets you define a single-line, nameless function on the fly.

The format for using lambda is as follows:

lambda arg: #do something with arg in a single line

Here's an example:

square = lambda x: x**2

Now, we can call the square method, as follows:

>>> print(square(5)) ## prints 25 to the console

Limitations of the command option

The command option that is available with the Button widget and a few other widgets is a function that can make the programming of a click-of-a-button event easy. Many other widgets do not provide an equivalent command binding option.

By default, the command button binds to the left-click and the space bar. It does not bind to the return key. Therefore, if you bind a button by using the command function, it will react to the space bar and not the return key. This is counter-intuitive for many users. What's worse is that you cannot change the binding of the command function easily. The moral is that the command binding, though a very handy tool, is not flexible enough when it comes to deciding your own bindings.

Event binding

Fortunately, Tkinter provides an alternative form of an event binding mechanism called bind() to let you deal with different events. The standard syntax used to bind an event is as follows:

widget.bind(event, handler, add=None)

When an event corresponding to the event description occurs in the widget, it calls not only the associated handler that passes an instance of the event object as the argument, but also the details of the event. If there already exists a binding for that event for this widget, the old callback is usually replaced with the new handler, but you can trigger both the callbacks by passing add='+' as the last argument.

Let's look at an example of the bind() method (refer to the 1.09.py code file):

from tkinter import *
root = Tk()
Label(root, text='Click at different\n locations in the frame below').pack()
def callback(event):
  print dir(event)
  print "you clicked at", event.x, event.y
frame = Frame(root, bg='khaki', width=130, height=80)
frame.bind("<Button-1>", callback)
frame.pack()
root.mainloop()

The following is a description of the preceding code:

  • We bind the Frame widget to the <Button-1> event, which corresponds to the left-click. When this event occurs, it calls the callback function, passing an object instance as its argument.
  • We define the callback(event) function. Note that it takes the event object generated by the event as an argument.
  • We inspect the event object by using dir(event), which returns a sorted list of attribute names for the event object passed to it. This prints the following list:

    ['__doc__', '__module__', 'char', 'delta', 'height', 'keycode', 'keysym', 'keysym_num', 'num', 'send_event', 'serial', 'state', 'time', 'type', 'widget', 'width', 'x', 'x_root', 'y', 'y_root']

  • From the attributes list generated by the object, we use two attributes, event.x and event.y, to print the coordinates of the point of click.

When you run the preceding code (code 1.09.py), it produces a window, as shown in following screenshot:

Event binding

When you left-click anywhere in the yellow-colored frame within the root window, it outputs messages to the console. A sample message passed to the console is as follows:

['__doc__', '__module__', 'char', 'delta', 'height', 'keycode', 'keysym', 'keysym_num', 'num', 'send_event', 'serial', 'state', 'time', 'type', 'widget', 'width', 'x', 'x_root', 'y', 'y_root']
You clicked at 63 36.

Event patterns

In the previous example, you learned how to use the <Button-1> event to denote a left-click. This is a built-in pattern in Tkinter that maps it to a left-click event. Tkinter has an exhaustive mapping scheme that perfectly identifies events such as this one.

Here are some examples to give you an idea of event patterns:

The event pattern

The associated event

<Button-1>

Left-click of the mouse

<KeyPress-B>

A keyboard press of the B key

<Alt-Control-KeyPress- KP_Delete>

A keyboard press of Alt + Ctrl + Delete

In general, the mapping pattern takes the following form:

<[event modifier-]...event type [-event detail]>

Typically, an event pattern will comprise the following:

  • An event type: Some common event types include Button, ButtonRelease, KeyRelease, Keypress, FocusIn, FocusOut, Leave (when the mouse leaves the widget), and MouseWheel. For a complete list of event types, refer to the The event types section at http://www.tcl.tk/man/tcl8.6/TkCmd/bind.htm#M7.
  • An event modifier (optional): Some common event modifiers include Alt, Any (used like <Any-KeyPress>), Control, Double (used like <Double-Button-1> to denote a double-click of the left mouse button), Lock, and Shift. For a complete list of event modifiers, refer to the The event modifiers section at http://www.tcl.tk/man/tcl8.6/TkCmd/bind.htm#M6.
  • The event detail (optional): The mouse event detail is captured by the number 1 for a left-click and the number 2 for a right-click. Similarly, each key press on the keyboard is either represented by the key letter itself (say, B in <KeyPress-B>) or by using a key symbol abbreviated as keysym. For example, the up arrow key on the keyboard is represented by the keysym value of KP_Up. For a complete keysym mapping, refer to https://www.tcl.tk/man/tcl8.6/TkCmd/bind.htm.

Let's take a look at a practical example of the event binding on widgets (refer to code 1.10.py for the complete working example).

Event patterns

The following is a modified snippet of code; it will give you an idea of the commonly used event bindings:

widget.bind("<Button-1>", callback)  #bind widget to left mouse click
widget.bind("<Button-2>", callback) # bind to right mouse click
widget.bind("<Return>", callback)# bind  to Return(Enter) Key
widget.bind("<FocusIn>", callback) #bind  to  Focus in Event
widget.bind("<KeyPress-A>", callback)# bind  to keypress A
widget.bind("<KeyPress-Caps_Lock>", callback)# bind to CapsLock keysym
widget.bind("<KeyPress-F1>", callback)# bind widget to F1 keysym
widget.bind("<KeyPress-KP_5>", callback)# bind to keypad number 5
widget.bind("<Motion>", callback) # bind to motion over widget
widget.bind("<Any-KeyPress>", callback) # bind to any keypress

Rather than binding an event to a particular widget, you can also bind it to the top, level window. The syntax remains the same except that now you call it on the root instance of the root window like root.bind().

The levels of binding

In the previous section, you had a look at how to bind an event to an instance of a widget. This can be called an instance-level binding.

However, there may be times when you need to bind events to an entire application. At times, you may want to bind an event to a particular class of widget. Tkinter provides the following levels of binding options for this:

  • Application-level binding: Application-level bindings let you use the same binding across all windows and widgets of an application as long as any one window of the application is in focus.

    The syntax for application-level bindings is as follows:

    widget.bind(event, callback, add=None)

    The typical usage pattern is as follows:

    root.bind_all('<F1>', show_help)

    An application-level binding here means that irrespective of the widget that is currently under focus, pressing the F1 key will always trigger the show_help callback as long as the application is in focus.

  • Class-level binding: You can also bind events at a particular class level. This is normally used to set the same behavior for all instances of a particular widget class.

    The syntax for class-level binding is as follows:

    w.bind_class(class_name, event, callback, add=None)

    The typical usage pattern is as follows:

    my_entry.bind_class('Entry', '<Control-V>', paste)

In the preceding example, all the entry widgets will be bound to the <Control-V> event, which will call a method named paste (event).

Tip

Event propagation

Most keyboard and mouse events occur at the operating system level. It propagates hierarchically upwards from the source of the event until it finds a window that has the corresponding binding. The event propagation does not stop there. It propagates itself upwards, looking for other bindings from other widgets, until it reaches the root window. If it does reach the root window and no bindings are discovered by it, the event is disregarded.

Handling widget-specific variables

You need variables with a wide variety of widgets. You likely need a string variable to track what the user enters into the entry widget or text widget. You most probably need Boolean variables to track whether the user has checked off the Checkbox widget. You need integer variables to track the value entered in a Spinbox or Slider widget.

In order to respond to changes in widget-specific variables, Tkinter offers its own variable class. The variable that you can use to track widget-specific values must be subclassed from this Tkinter variable class. Tkinter offers some commonly used predefined variables. They are StringVar, IntVar, BooleanVar, and DoubleVar.

You can use these variables to capture and play with the changes in the values of variables from within your callback functions. You can also define your own variable type, if required.

Creating a Tkinter variable is simple. You simply have to call the constructor:

my_string = StringVar()
ticked_yes = BooleanVar()
group_choice = IntVar()
volume = DoubleVar()

Once the variable is created, you can use it as a widget option, as follows:

Entry(root, textvariable=my_string)
Checkbutton(root, text="Remember Me", variable=ticked_yes)
Radiobutton(root, text="Option1", variable=group_choice, value="option1") #radiobutton
Scale(root, label="Volume Control", variable=volume, from =0, to=10) # slider

Additionally, Tkinter provides access to the values of variables via the set() and get() methods, as follows:

my_var.set("FooBar") # setting value of variable
my_var.get() # Assessing the value of variable from say a callback

A demonstration of the Tkinter variable class is available in the 1.11.py code file. The code generates a window, as shown in the following screenshot:

Handling widget-specific variables

This concludes our brief discussion on events and callbacks. Here's a brief summary of the things that we discussed:

  • The command binding, which is used to bind simple widgets to certain functions
  • The use of the lambda function in case you need to process arguments
  • Event binding using the widget.bind(event, callback, add=None) method to bind keyboard and mouse events to your widgets and invoke callbacks when certain events occur
  • The passing of extra arguments to a callback
  • The binding of events to an entire application or to a particular class of widget by using bind_all() and bind_class()
  • Using the Tkinter variable class to set and get the values of widget-specific variables

In short, you now know how to make your GUI program responsive to end-user requests!

Event unbinding and virtual events

In addition to the bind method that you previously saw, you might find the following two event-related options useful in certain cases:

  • unbind: Tkinter provides the unbind option to undo the effect of an earlier binding. The syntax is as follows:
    widget.unbind(event)

    The following are some examples of its usage:

    entry.unbind('<Alt-Shift-5>')
    root.unbind_all('<F1>')
    root.unbind_class('Entry', '<KeyPress-Del>')
  • Virtual events: Tkinter also lets you create your own events. You can give these virtual events any name that you want.

    For example, let's suppose that you want to create a new event called <<commit>>, which is triggered by the F9 key. To create this virtual event on a given widget, use the following syntax:

    widget.event_add('<<commit>>', '<KeyRelease-F9>')
  • You can then bind <<commit>> to a callback by using a normal bind() method, as follows:
    widget.bind('<<commit>>', callback)

Other event-related methods can be accessed by typing the following line in the Python terminal:

>>> import tkinter
>>> help(tkinter.Event)

Now that you are ready to dive into real application development with Tkinter, let's spend some time exploring a few custom styling options that Tkinter offers. We will also have a look at some of the configuration options that are commonly used with the root window.

Doing it in style

So far, we have relied on Tkinter to provide specific platform-based styling for our widgets. However, you can specify your own styling of widgets, such as their color, font size, border width, and relief. A brief introduction of styling features that are available in Tkinter is covered in the following section.

You may recall that we can specify the widget options at the time of its instantiation, as follows:

my_button = Button(parent, **configuration options)

Alternatively, you can specify the widget options by using configure () in the following way:

my_button.configure(**options)

The styling options are also specified as options to the widgets either at the time of creating the widgets, or later by using the configure option.

Specifying styles

Under the purview of styling, we will cover how to apply different colors, fonts, border widths, reliefs, cursors, and bitmap icons to widgets.

First, let's see how to specify the color options for a widget. You can specify the following two types of color for most widgets:

  • The background color
  • The foreground color

You can specify the color by using hexadecimal color codes for the proportion of red, green, and blue. The commonly used representations are #rgb (4 bits), #rrggbb (8 bits), and #rrrgggbbb (12 bits).

For example, #fff is white, #000000 is black, #f00 is red (R=0xf, G=0x0, B=0x0), #00ff00 is green (R=0x00, G=0xff, B=0x00), and #000000fff is blue (R=0x000, G=0x000, B=0xfff).

Alternatively, Tkinter provides mapping for standard color names. For a list of predefined named colors, visit http://wiki.tcl.tk/37701 or http://wiki.tcl.tk/16166.

Next, let's have a look at how to specify fonts for our widgets. A font can be represented as a string by using the following string signature:

{font family} fontsize fontstyle

The elements of the preceding syntax can be explained as follows:

  • font family: This is the complete font family long name. It should preferably be in lowercase, such as font="{nimbus roman} 36 bold italic".
  • fontsize: This is in a printer's point unit (pt) or pixel unit (px).
  • fontstyle: This is a mix of normal/bold/italic and underline/overstrike.

The following are the examples that illustrate the method of specifying fonts:

widget.configure (font='Times 8')
widget.configure(font='Helvetica 24 bold italic')

If you set a Tkinter dimension in a plain integer, the measurements take place in pixel units. Alternatively, Tkinter accepts four other measurement units, which are m (millimeters), c (centimeters), i (inches), and p (printer's points, which are about 1/72").

For instance, if you want to specify the wrap length of a button in terms of a printer's point, you can specify it as follows:

button.configure(wraplength="36p")

The default border width for most Tkinter widgets is 2 px. You can change the border width of the widgets by specifying it explicitly, as shown in the following line:

button.configure(borderwidth=5)

The relief style of a widget refers to the difference between the highest and lowest elevations in a widget. Tkinter offers six possible relief styles—flat, raised, sunken, groove, solid, and ridge:

button.configure(relief='raised')

Tkinter lets you change the style of the mouse cursor when you hover over a particular widget. This is done by using the option cursor, as follows:

button.configure(cursor='cross')

For a complete list of available cursors, refer to https://www.tcl.tk/man/tcl8.6/TkCmd/cursors.htm.

Though you can specify the styling options at each widget level, sometimes it may be cumbersome to do so individually for each widget. Widget-specific styling has the following disadvantages:

  • It mixes logic and presentation into one file, making the code bulky and difficult to manage
  • Any change in styling has to be applied to each widget individually
  • It violates the don't repeat yourself (DRY) principle of effective coding, as you keep specifying the same style for a large number of widgets

Fortunately, Tkinter now offers a way to separate presentation from logic and specify styles in what is called the external option database. This is nothing but a text file where you can specify the common styling options.

A typical option database text file looks like this:

*background: AntiqueWhite1
*Text*background: #454545
*Button*foreground: gray55
*Button*relief: raised
*Button*width: 3

In its simplest use, the asterisk (*) symbol here means that the particular style is applied to all the instances of the given widget. For a more complex usage of the asterisk in styling, refer to http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/resource-lines.html.

These entries are placed in an external text (.txt) file. To apply this styling to a particular piece of code, you can simply call it by using the option_readfile() call early in your code, as shown here:

root.option_readfile('optionDB.txt')

Let's have a look at an example (see code 1.12.py) of using this external styling text file in a program:

from tkinter import *
root = Tk()
root.configure(background='#4D4D4D')#top level styling

# connecting to the external styling optionDB.txt
root.option_readfile('optionDB.txt')

#widget specific styling
mytext = Text(root, background='#101010', foreground="#D6D6D6", borderwidth=18, relief='sunken',width=17, height=5)
mytext.insert(END, "Style is knowing who you are, what you want to say, and not giving a damn.")
mytext.grid(row=0, column=0, columnspan=6, padx=5, pady=5)

# all the below widgets derive their styling from optionDB.txt file
Button(root, text='*').grid(row=1, column=1)
Button(root, text='^').grid(row=1, column=2)
Button(root, text='#').grid(row=1, column=3)
Button(root, text='<').grid(row=2, column=1)
Button(root, text='OK', cursor='target').grid(row=2, column=2)#changing cursor style
Button(root, text='>').grid(row=2, column=3)
Button(root, text='+').grid(row=3, column=1)
Button(root, text='v').grid(row=3, column=2)
Button(root, text='-').grid(row=3, column=3)
for i in range(9):
  Button(root, text=str(i+1)).grid(row=4+i//3, column=1+i%3)

root.mainloop()

The following is a description of the preceding code:

  • The code connects to an external styling file called optionDB.txt that defines common styling for the widgets.
  • The next segment of code creates a Text widget and specifies styling on the widget level.
  • The next segment of code has several buttons, all of which derive their styling from the centralized optionDB.txt file. One of the buttons also defines a custom cursor.

Specifying attributes such as font sizes, the border width, the widget width, the widget height, and padding in absolute numbers, as we have done in the preceding example, can cause some display variations between different operating systems such as Ubuntu, Windows, and Mac respectively, as shown in the following screenshot. This is due to differences in the rendering engines of different operating systems.

Specifying styles

Left: Ubuntu, Middle: Microsoft Windows, Right: Mac OS X

Tip

When deploying cross-platform, it is better to avoid specifying attribute sizes in absolute numbers. It is often the best choice to let the platform handle the attribute sizes.

Some common root window options

Now that we are done discussing styling options, let's wrap up with a discussion on some commonly used options for the root window:

Method

Description

*root.geometry('142x280+150+200')

You can specify the size and location of a root window by using a string of the widthxheight + xoffset + yoffset form.

** self.root.wm_iconbitmap('mynewicon.ico')

or

self.root.iconbitmap('mynewicon.ico ')

This changes the title bar icon to something that is different from the default Tk icon.

root.overrideredirect(1)

This removes the root border frame. It hides the frame that contains the minimize, maximize, and close buttons.

Let's explain these styling options in more detail:

  • root.geometry('142x280+150+200'): Specifying the geometry of the root window limits the launch size of the root window. If the widgets do not fit in the specified size, the widgets get clipped from the window. It is often better not to specify this and let Tkinter decide this for you.
  • self.root.wm_iconbitmap('my_icon.ico') or self.root.iconbitmap('my_icon.ico '): This option is only applicable to Windows. Unix-based operating systems do not display the title bar icon.

Getting interactive help

This section is true not only for Tkinter, but also for a Python object for which you may need help.

Let's say that you need a reference to the Tkinter pack geometry manager. You can get interactive help in your Python interactive shell by using the help command, as shown in the following command lines:

>>> import tkinter
>>> help(tkinter.Pack)

This provides a detailed help documentation of all the methods defined under the Pack class in Tkinter.

You can similarly receive help for all the other individual widgets. For instance, you can check the comprehensive and authoritative help documentation for the Label widget in the interactive shell by typing the following command:

>>>help(tkinter.Label)

This provides a list of the following:

  • All the methods defined in the Label class
  • All the standard and widget-specific options for the Label widget
  • All the methods inherited from other classes

Finally, when in doubt regarding a method, look into the source code of Tkinter, which is located at <location-of-python-installation>\lib\ directory. For instance, the Tkinter source code is located in the /usr/lib/python3.4/tkinter directory on my Ubuntu 14.04 operating system.

Tip

You might also find it useful to look at the source code implementation of various other modules, such as the color chooser, file dialogs, ttk module, and the other modules located in the aforementioned directory.

You can also find an excellent documentation of Tkinter at http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html.

Summary

This brings us to end of Chapter 1, Meet Tkinter. This chapter is aimed to provide a high-level overview of Tkinter. We worked our way through all the important concepts that drive a Tkinter program.

You now know what a root window is and how to set it up. You also know the 21 core Tkinter widgets and how to set them up. We also had a look at how to lay out our programs by using the pack, grid, and place geometry managers, and make our programs functional by using events and callbacks. Finally, you saw how to apply custom styles to GUI programs.

To summarize, we can now start thinking of making interesting, functional, and stylish GUI programs with Tkinter!

Left arrow icon Right arrow icon

Key benefits

  • Conceptualize and build state-of-art GUI applications with Tkinter
  • Tackle the complexity of just about any size GUI application with a structured and scalable approach
  • A project-based, practical guide to get hands-on into Tkinter GUI development

Description

Tkinter is the built-in GUI package that comes with standard Python distributions. It is a cross-platform package, which means you build once and deploy everywhere. It is simple to use and intuitive in nature, making it suitable for programmers and non-programmers alike. This book will help you master the art of GUI programming. It delivers the bigger picture of GUI programming by building real-world, productive, and fun applications such as a text editor, drum machine, game of chess, media player, drawing application, chat application, screen saver, port scanner, and many more. In every project, you will build on the skills acquired in the previous project and gain more expertise. You will learn to write multithreaded programs, network programs, database driven programs and more. You will also get to know the modern best practices involved in writing GUI apps. With its rich source of sample code, you can build upon the knowledge gained with this book and use it in your own projects in the discipline of your choice.

Who is this book for?

Software developers, scientists, researchers, engineers, students, or programming hobbyists with basic familiarity in Python will find this book interesting and informative. People familiar with basic programming constructs in other programming language can also catch up with some brief reading on Python. No GUI programming experience is expected.

What you will learn

  • Get to know the basic concepts of GUI
  • programming, such as Tkinter top-level
  • widgets, geometry management, event
  • handling, using callbacks, custom styling,
  • and dialogs
  • Create apps that can be scaled in size or
  • complexity without breaking down the core
  • Write your own GUI framework for maximum
  • code reuse
  • Build apps using both procedural and OOP
  • styles, understanding the strengths and
  • limitations of both styles
  • Learn to structure and build large GUI
  • applications based on Model-View-Controller
  • (MVC) architecture
  • Build multithreaded and database-driven apps
  • Create apps that leverage resources from
  • the network
  • Learn basics of 2D and 3D animation in GUI
  • applications
  • Develop apps that can persist application
  • data with object serialization and tools such
  • as configparser
Estimated delivery fee Deliver to South Korea

Standard delivery 10 - 13 business days

$12.95

Premium delivery 5 - 8 business days

$45.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Nov 30, 2015
Length: 340 pages
Edition : 1st
Language : English
ISBN-13 : 9781785889738
Category :
Languages :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to South Korea

Standard delivery 10 - 13 business days

$12.95

Premium delivery 5 - 8 business days

$45.95
(Includes tracking information)

Product Details

Publication date : Nov 30, 2015
Length: 340 pages
Edition : 1st
Language : English
ISBN-13 : 9781785889738
Category :
Languages :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total $ 97.98
Python GUI Programming Cookbook
$48.99
Tkinter GUI Application Development Blueprints
$48.99
Total $ 97.98 Stars icon
Banner background image

Table of Contents

9 Chapters
1. Meet Tkinter Chevron down icon Chevron up icon
2. Making a Text Editor Chevron down icon Chevron up icon
3. Programmable Drum Machine Chevron down icon Chevron up icon
4. A Game of Chess Chevron down icon Chevron up icon
5. Building an Audio Player Chevron down icon Chevron up icon
6. Paint Application Chevron down icon Chevron up icon
7. Multiple Fun Projects Chevron down icon Chevron up icon
8. Miscellaneous Tips Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon

Customer reviews

Top Reviews
Rating distribution
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
(28 Ratings)
5 star 57.1%
4 star 21.4%
3 star 3.6%
2 star 0%
1 star 17.9%
Filter icon Filter
Top Reviews

Filter reviews by




pdxJaxon Mar 11, 2016
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This book is Exceptional.I initially purchased it because I was struggling with the Tkinter libraries. Turns out this book is an excellent book on simply learning Python.This one book really gets a person jump started in Python.if you are new to Python, this book is a MUST BUY.
Amazon Verified review Amazon
Tom Dettloff Jan 01, 2020
Full star icon Full star icon Full star icon Full star icon Full star icon 5
I most appreciated the volume of detail represented by the scripts and overviews in the book. It took awhile to get through it all but I must say that each project was quite an eye opener as to the scope of Tkinter usage. Definitely need to download the examples zip file.
Amazon Verified review Amazon
Amazon Customer Feb 17, 2016
Full star icon Full star icon Full star icon Full star icon Full star icon 5
I wish I had found this book earlier. Lots of great examples. Excellent coding practice. Well worth the money.The book goes beyond Tkinter to include extension like ttk. It also offers excellent programming and program optimization advice. It would be helpful if the reader had some gui programming experience--if nothing else than to know the value of this book.
Amazon Verified review Amazon
William Fehlman Dec 21, 2015
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Finally an up-to-date guide with practical hands-on projects using Tkinter (“Tk interface”), the standard built-in GUI module in Python. This book presents the features and capabilities of Tkinter while demonstrating best practices involved in writing GUI programs with Tkinter and Python. It's obvious that the author has experience educating in the field of software development since he does an excellent job presenting and explaining the Python code.
Amazon Verified review Amazon
John L Stalder Aug 17, 2017
Full star icon Full star icon Full star icon Full star icon Full star icon 5
I have been trying to self-learn Python and how to make a reasonable GUI, but was struggling with too many new things to learn just to get started. This book was perfect! The first chapter very efficiently walks the reader through all the essential features and widgets to create GUI's for almost any imaginable task. Later chapters focus on detailed applications of what was given in summary form in chapter 1. I would recommend the free download of all the example code as it is tedious to type all the examples covered without a typo here or there resulting in debugging.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela