8.5. Tkinter Coding Basics
The gui1 script is a trivial example, but it illustrates steps common to most Tkinter programs. This Python code does the following:
The mainloop method called last puts the label on the screen and enters a Tkinter wait state, which watches for user-generated GUI events. Within the mainloop function, Tkinter internally monitors things such as the keyboard and mouse to detect user-generated events. In fact, the Tkinter mainloop function is similar in spirit to the following pseudo-Python code:
def mainloop( ): while the main window has not been closed: if an event has occurred: run the associated event handler function
Because of this model, the mainloop call in Example 8-1 never returns to our script while the GUI is displayed on-screen.[*] When we write larger scripts, the only way we can get anything done after calling mainloop is to register callback handlers to respond to events.
This is called event-driven programming, and it is perhaps one of the most unusual aspects of GUIs. GUI programs take the form of a set of event handlers that share saved information rather than of a single main control flow. We'll see how this looks in terms of real code in later examples.
Note that in a script, you really need steps 3 and 4 in the preceding list to open this script's GUI. To display a GUI's window at all, you need to call mainloop; to display widgets within the window, they must be packed (or otherwise arranged) so that the Tkinter geometry manager knows about them. In fact, if you call either mainloop or pack without calling the other, your window won't show up as expected: a mainloop without a pack shows an empty window, and a pack without a mainloop in a script shows nothing since the script never enters an event wait state (try it).
Since the concepts illustrated by this simple script are at the core of most Tkinter programs, let's take a deeper look at some of them before moving on.
8.5.1. Making Widgets
When widgets are constructed in Tkinter, we can specify how they should be configured. The gui1 script passes two arguments to the Label class constructor:
As we'll see, the parent-widget argument is the hook we use to build up complex GUIs as widget trees. Tkinter works on a "what-you-build-is-what-you-get" principle: we construct widget object trees as models of what we want to see on the screen, and then ask the tree to display itself by calling mainloop.
8.5.2. Geometry Managers
The pack widget method called by the gui1 script invokes the packer geometry manager, one of three ways to control how widgets are arranged in a window. Tkinter geometry managers simply arrange one or more widgets within a container (sometimes called a parent or master). Both top-level windows and frames (a special kind of widget we'll meet later) can serve as containers, and containers may be nested inside other containers to build hierarchical displays.
The packer geometry manager uses constraint option settings to automatically position widgets in a window. Scripts supply higher-level instructions (e.g., "attach this widget to the top of its container, and stretch it to fill its space vertically"), not absolute pixel coordinates. Because such constraints are so abstract, the packer provides a powerful and easy-to-use layout system. In fact, you don't even have to specify constraints. If you don't pass any arguments to pack, you get default packing, which attaches the widget to the top side of its container.
We'll visit the packer repeatedly in this chapter and use it in many of the examples in this book. In Chapter 10, we will also meet an alternative grid geometry manager and layout system that arranges widgets within a container in tabular form (i.e., by rows and columns). A third alternative, called the placer geometry manager system, is described in Tk documentation but not in this book; it's less popular than the pack and grid managers and can be difficult to use for larger GUIs.
8.5.3. Running GUI Programs
Like all Python code, the module in Example 8-1 can be started in a number of ways: by running it as a top-level program file:
by importing it from a Python session or another module file:
>>> import gui1
by running it as a Unix executable if we add the special #! line at the top:
% gui1.py &
and in any other way Python programs can be launched on your platform. For instance, the script can also be run by clicking on the file's name in a Windows file explorer, and its code can be typed interactively at the >>> prompt.[*] It can even be run from a C program by calling the appropriate embedding API function (see Chapter 23 for details).
In other words, there are really no special rules to follow when running GUI Python code. The Tkinter interface (and Tk itself) is linked into the Python interpreter. When a Python program calls GUI functions, they're simply passed to the embedded GUI system behind the scenes. That makes it easy to write command-line tools that pop up windows; they are run the same way as the purely text-based scripts we studied in the prior part of this book.
188.8.131.52. Avoiding DOS consoles on Windows
Earlier in this book we learned that if a program's name ends in a .pyw extension rather than a .py extension, the Windows Python port does not pop up a DOS console box to serve as its standard streams when the file is launched by clicking its filename icon. Now that we've finally started making windows of our own, that filename trick will start to become even more useful.
If you just want to see the windows that your script makes no matter how it is launched, be sure to name your GUI scripts with a .pyw if they might be run on Windows. For instance, clicking on the file in Example 8-2 in a Windows explorer creates just the window in Figure 8-1.
Example 8-2. PP3E\Gui\Intro\gui1.pyw
You can also avoid the DOS pop up on Windows by running the program with the pythonw.exe executable, not python.exe (in fact, .pyw files are simply registered to be opened by pythonw). On Linux, the .pyw doesn't hurt, but it isn't necessary; there is no notion of a streams pop up on Unix-like machines. On the other hand, if your GUI scripts might run on Windows in the future, adding an extra "w" at the end of their names now might save porting effort later. In this book, .py filenames are still sometimes used to pop up console windows for viewing printed messages on Windows.