The PyGadgets
script runs some of the same programs as PyDemos, but for
real, practical use, not as demonstrations. Both scripts uselaunchmodes
to spawn other programs, and
display bars of launcher buttons, but PyGadgets is a bit simpler because
its task is more focused. PyGadgets also supports two spawning modes—it
can either start a canned list of programs immediately and all at once,
or display a GUI for running each program on demand.
Figure 10-19
shows the launch bar GUI made in
on-demand mode when it first starts; PyDemos and PyGadgets can be run at
the same time, and both grow with their window if resized (try it on
your own to see how).
Figure 10-19. PyGadgets launcher bar
Because of its different role, PyGadgets takes a more data-driven
approach to building the GUI: it stores program names in a list and
steps through it as needed instead of using a sequence of precodeddemoButton
calls. The set of buttons
on the launcher bar GUI in
Figure 10-19
, for example, depends entirely
upon the contents of the programs list.
The source code behind this GUI is listed in
Example 10-31
. It’s not much because it
relies on other modules we wrote earlier to work most of its magic:launchmodes
for program spawns,windows
for window icons and quits,
andLaunchBrowser
for web browser
starts. PyGadgets gets a clickable shortcut on my desktop and is usually
open on my machines. I use to gain quick access to Python tools that I
use on a daily
basis—
text editors,
calculators, email and photo tools, and so on—all of which we’ll meet in
upcoming chapters.
To customize PyGadgets for your own use, simply import and call
its functions with program command-line lists of your own or change themytools
list of spawnable programs
near the end of this file. This is Python, after all.
Example 10-31. PP4E\PyGadgets.py
"""
##############################################################################
Start various examples; run me at start time to make them always available.
This file is meant for starting programs you actually wish to use; see
PyDemos for starting Python/Tk demos and more details on program start
options. Windows usage note: this is a '.py' to show messages in a console
window when run or clicked (including a 10 second pause to make sure it's
visible while gadgets start if clicked). To avoid Windows console pop up,
run with the 'pythonw' program (not 'python'), rename to '.pyw' suffix,
mark with 'run minimized' window property, or spawn elsewhere (see PyDemos).
##############################################################################
"""
import sys, time, os, time
from tkinter import *
from launchmodes import PortableLauncher # reuse program start class
from Gui.Tools.windows import MainWindow # reuse window tools: icon, quit
def runImmediate(mytools):
"""
launch gadget programs immediately
"""
print('Starting Python/Tk gadgets...') # msgs to stdout (poss temp)
for (name, commandLine) in mytools:
PortableLauncher(name, commandLine)() # call now to start now
print('One moment please...')
if sys.platform[:3] == 'win': # windows: keep console 10 secs
for i in range(10):
time.sleep(1); print('.' * 5 * (i+1))
def runLauncher(mytools):
"""
pop up a simple launcher bar for later use
"""
root = MainWindow('PyGadgets PP4E') # or root = Tk() if prefer
for (name, commandLine) in mytools:
b = Button(root, text=name, fg='black', bg='beige', border=2,
command=PortableLauncher(name, commandLine))
b.pack(side=LEFT, expand=YES, fill=BOTH)
root.mainloop()
mytools = [
('PyEdit', 'Gui/TextEditor/textEditor.py'),
('PyCalc', 'Lang/Calculator/calculator.py'),
('PyPhoto', 'Gui/PIL/pyphoto1.py Gui/PIL/images'),
('PyMail', 'Internet/Email/PyMailGui/PyMailGui.py'),
('PyClock', 'Gui/Clock/clock.py -size 175 -bg white'
' -picture Gui/gifs/pythonPowered.gif'),
('PyToe', 'Ai/TicTacToe/tictactoe.py'
' -mode Minimax -fg white -bg navy'),
('PyWeb', 'LaunchBrowser.pyw'
' -live index.html learning-python.com')]
#' -live PyInternetDemos.html localhost:80')]
#' -file')] # PyInternetDemos assumes local server started
if __name__ == '__main__':
prestart, toolbar = True, False
if prestart:
runImmediate(mytools)
if toolbar:
runLauncher(mytools)
By default, PyGadgets starts programs immediately when it is run.
To run PyGadgets in launcher bar mode instead,
Example 10-32
simply imports and
calls the appropriate function with an imported program list. Because it
is a
.pyw
file, you see only the launcher bar GUI
it constructs initially, not a DOS console streams window—nice for
regular use, but not if you want to see error messages (use a
.py
).
Example 10-32. PP4E\PyGadgets_bar.pyw
"""
run a PyGadgets toolbar only, instead of starting all the gadgets immediately;
filename avoids DOS pop up on Windows: rename to '.py' to see console messages;
"""
import PyGadgets
PyGadgets.runLauncher(PyGadgets.mytools)
This script is the file my desktop shortcut invokes, because I
prefer to run gadget GUIs on demand. On many platforms, you can drag
this out as a shortcut on your desktop for easy access this way. You can
also run a script like this at your system’s startup to make it always
available (and to save a mouse click). For instance, on Windows, such a
script might be automatically started by adding it to your Startup
folder, and on Unix and its kin you can automatically start such a
script by spawning it with a command line in your system startup scripts
after X Windows has been started.
Whether run via a shortcut, a file explorer click, a typed command
line, or other means, the PyGadgets launcher bar near the center of
Figure 10-20
appears.
Figure 10-20. PyGadgets launcher bar with gadgets
Of course, the whole point of PyGadgets is to spawn other
programs. Pressing on its launcher bar’s buttons starts programs like
those shown in the rest of
Figure 10-20
, but if you want to
know more about those, you’ll have to turn the page and move on to the
next
chapter.
This chapter concludes our look at building GUIs with Python and its
standard tkinter library, by presenting a collection of realistic GUI
programs. In the preceding four chapters, we met all the basics of tkinter
programming. We toured the core set of
widgets
—Python
classes that generate devices on a computer screen and respond to user
events—and we studied a handful of advanced GUI programming techniques,
including automation tools, redirection with sockets and pipes, and
threading. Here, our focus is on putting those widgets and techniques
together to create more useful GUIs. We’ll study:
A text editor program
A thumbnail photo viewer
An image slideshow
A painting program
A graphical clock
A simple tic-tac-toe game, just for fun
[
38
]
As in
Part II
’s
Chapter 6
, I’ve pulled the examples in this
chapter from my own library of Python programs that I really use. For
instance, the text editor and clock GUIs that we’ll meet here are
day-to-day workhorses on my machines. Because they are written in Python
and tkinter, they work unchanged on my Windows and Linux machines, and
they should work on Macs too.
Since these are pure Python scripts, their future evolution is
entirely up to their
users—
once you
get a handle on tkinter interfaces, changing or augmenting the behavior of
such programs by editing their Python code is a snap. Although some of
these examples are similar to commercially available programs (e.g.,
PyEdit is reminiscent of the Windows Notepad accessory), the portability
and almost infinite configurability of Python scripts can be a decided
advantage.
Later in the book, we’ll meet other tkinter GUI programs that put
a good face on specific application domains. For instance, the following
larger GUI examples show up in later chapters also:
A comprehensive email client (
Chapter 14
)
A (mostly external) persistent object table viewer (
Chapter 17
)
A (mostly external) tree data structure viewer (
Chapter 18
and
Chapter 19
)
A customizable calculator widget (
Chapter 19
)
Smaller examples, including FTP and file-transfer GUIs, pop up in
the Internet part as well. Most of these programs see regular action on
my desktop, too. Because GUI libraries are general-purpose tools, there
are very few domains that cannot benefit from an easy-to-use,
easy-to-program, and widely portable user interface coded in Python and
tkinter.
Beyond the examples in this book, you can also find higher-level
GUI toolkits for Python, such as the Pmw, Tix, and ttk packages
introduced in
Chapter 7
. Some such
systems build upon tkinter to provide compound components such as
notebook tabbed widgets, tree views, and balloon pop-up help.
In the next part of the book, we’ll also explore programs that
build user interfaces in web browsers, instead of tkinter—a very
different way of approaching the user interface experience. Although web
browser interfaces have been historically limited in functionality and
slowed by network latency, when combined with the rich Internet
application (RIA) toolkits mentioned at the start of
Chapter 7
, browser-based GUIs today can
sometimes approach the utility of traditional GUIs, albeit at
substantial cost in software complexity and dependencies.
Especially for highly interactive and nontrivial interfaces,
though, standalone/desktop tkinter GUIs can be an indispensable feature
of almost any Python program you write. The programs in this chapter
underscore just how far Python and tkinter can take you.
As for all case-study chapters in this text, this one is largely a
learn-by-example exercise; most of the programs here are listed with
minimal details. Along the way, I’ll highlight salient points and
underscore new tkinter features that examples introduce, but I’ll also
assume that you will study the listed source code and its comments for
more information. Once we reach the level of complexity demonstrated by
programs here, Python’s readability becomes a substantial advantage for
programmers (and writers of books).
All of this book’s GUI examples are available in source code form
in the book’s examples distribution described in the
Preface
. Because I’ve already shown the interfaces these
scripts employ, this section consists mostly of screenshots, program
listings, and a few brief words describing some of the most important
aspects of these programs. In other words, this is a self-study section:
read the source, run the examples on your own computer, and refer to the
previous chapters for further details on the code listed here. Some of
these programs may also be accompanied in the book examples distribution
by alternative or experimental implementations not listed here; see the
distribution for extra code examples.
Finally, I want to remind you that all of the larger programs
listed in the previous sections can be run from the
PyDemos and PyGadgets launcher bar GUIs that we met at the
end of
Chapter 10
. Although I will try
hard to capture some of their behavior in screenshots here, GUIs are
event-driven systems by nature, and there is nothing quite like running
one live to sample the flavor of its user interactions. Because of that,
the launcher bars are really a supplement to the material in this
chapter. They should run on most platforms and are designed to be easy
to start (see the top-level
README-PP4E.txt
file
for hints). You should go there and start clicking things immediately if
you haven’t done so already.
Open Source Software and Camaros
Some of the GUI
programs in this chapter, as well as the rest of the
book, are analogous to utilities found on commonly used operating
systems like Windows. For instance, we’ll meet calculators, text
editors, image viewers, clocks, email clients, and more.
Unlike most utilities, though, these programs are
portable
—because they are written in Python with
tkinter, they will work on all major platforms (Windows, Unix/Linux,
and Macs). Perhaps more important, because their source code is
available, they can be
scripted
—you can change
their appearance or function however you like, just by writing or
modifying a little Python code.
An analogy might help underscore the importance of
scriptability. There are still a few of us who remember a time when it
was completely normal for car owners to work on and repair their own
automobiles. I still fondly remember huddling with friends under the
hood of a 1970 Camaro in my youth, tweaking and customizing its
engine. With a little work, we could make it as fast, flashy, and loud
as we liked. Moreover, a breakdown in one of those older cars wasn’t
necessarily the end of the world. There was at least some chance that
I could get the car going again on my own.
That’s not quite true today. With the introduction of electronic
controls and diabolically cramped engine compartments, car owners are
usually better off taking their cars back to the dealer or another
repair professional for all but the simplest kinds of changes. By and
large, cars are no longer user-maintainable products. And if I have a
breakdown in my shiny new ride, I’m probably going to be completely
stuck until an authorized repair person can get around to towing and
fixing it.
I like to think of the closed and open software models in the
same terms. When I use Microsoft-provided programs such as Notepad and
Outlook, I’m stuck with the feature set that a large company dictates,
as well as any bugs that it may harbor. But with programmable tools
such as PyEdit and PyMailGUI, I can still get under the hood. I can
add features, customize the system, and work my way out of any lurking
bugs. And I can do so long before the next Microsoft patch or release
is available. I’m no longer dependent on a self-interested company to
support—or even to continue producing—the tools I use.
Of course, I’m still dependent on Python and whatever changes it
may dictate over time (and after updating two 1,000+ page books for
Python 3.X, I can say with some confidence that this dependency isn’t
always completely trivial). Having all the source code for every layer
of the tools you depend on, though, is still a powerful last resort,
and a major net win. As an added bonus, it fosters robustness by
providing a built-in group of people to test and hone the
system.
At the end of the day, open source software and Python are as
much about
freedom
as they are about cost. Users,
not an arbitrarily far-removed company, have the final say. Not
everyone wants to work on his own car, of course. On the other hand,
software tends to fail much more often than cars, and Python scripting
is generally less greasy than auto mechanics.
[
38
]
All of the larger examples in this book have
Py
at the start of their names. This is by
convention in the Python world. If you shop around at
http://www.python.org
, you’ll find other free
software that follows this pattern too: PyOpenGL (a Python
interface to the OpenGL graphics library), PyGame (a Python game
development kit), and many more. I’m not sure who started this
pattern, but it has turned out to be a more or less subtle way
to advertise programming language preferences to the rest of the
open source world. Pythonistas are nothing if not
PySubtle.