Read Programming Python Online

Authors: Mark Lutz

Tags: #COMPUTERS / Programming Languages / Python

Programming Python (54 page)

Standalone Container Classes

Before we move on, I want to
point out that it’s possible to reap most of the
class-based component benefits previously mentioned by creating
standalone classes not derived from tkinter
Frames
or other widgets. For instance, the
class in
Example 7-24
generates the window shown in
Figure 7-23
.

Example 7-24. PP4E\Gui\Intro\gui7.py

from tkinter import *
class HelloPackage: # not a widget subbclass
def __init__(self, parent=None):
self.top = Frame(parent) # embed a Frame
self.top.pack()
self.data = 0
self.make_widgets() # attach widgets to self.top
def make_widgets(self):
Button(self.top, text='Bye', command=self.top.quit).pack(side=LEFT)
Button(self.top, text='Hye', command=self.message).pack(side=RIGHT)
def message(self):
self.data += 1
print('Hello number', self.data)
if __name__ == '__main__': HelloPackage().top.mainloop()

Figure 7-23. A standalone class package in action

When run, the Hye button here prints to
stdout
and the Bye button closes and exits the
GUI, much as before:

C:\...\PP4E\Gui\Intro>
python gui7.py
Hello number 1
Hello number 2
Hello number 3
Hello number 4

Also as before,
self.data
retains state between events, and callbacks are routed to the
self.message
method within this class. Unlike
before, the
HelloPackage
class is not
itself a kind of
Frame
widget. In
fact, it’s not a kind of anything—it serves only as a generator of
namespaces for storing away real widget objects and state. Because of
that, widgets are attached to a
self.top
(an embedded
Frame
), not to
self
. Moreover, all references to the object
as a widget must descend to the embedded frame, as in the
top.mainloop
call to start the GUI at the end
of the script.

This makes for a bit more coding within the class, but it avoids
potential name clashes with both attributes added to
self
by the tkinter framework and existing
tkinter widget methods. For instance, if you define a
config
method in your class, it will hide the
config
call exported by tkinter. With
the standalone class package in this example, you get only the methods
and instance attributes that your class defines.

In practice, tkinter doesn’t use very many names,
so this is not generally a big concern.
[
31
]
It can happen, of course; but frankly, I’ve never seen a
real tkinter name clash in widget subclasses in some 18 years of Python
coding. Moreover, using standalone classes is not without other
downsides. Although they can generally be attached and subclassed as
before, they are not quite plug-and-play compatible with real widget
objects. For instance, the configuration calls made in
Example 7-21
for the
Frame
subclass fail in
Example 7-25
.

Example 7-25. PP4E\Gui\Intro\gui7b.py

from tkinter import *
from gui7 import HelloPackage # or get from gui7c--__getattr__ added
frm = Frame()
frm.pack()
Label(frm, text='hello').pack()
part = HelloPackage(frm)
part.pack(side=RIGHT) # FAILS!--need part.top.pack(side=RIGHT)
frm.mainloop()

This won’t quite work, because
part
isn’t really a widget. To treat it as
such, you must descend to
part.top
before making GUI configurations and hope that the name
top
is never changed by the class’s developer.
In other words, it exposes some of the class’s internals. The class
could make this better by defining a method that always routes unknown
attribute fetches to the embedded
Frame
, as in
Example 7-26
.

Example 7-26. PP4E\Gui\Intro\gui7c.py

import gui7
from tkinter import *
class HelloPackage(gui7.HelloPackage):
def __getattr__(self, name):
return getattr(self.top, name) # pass off to a real widget
if __name__ == '__main__': HelloPackage().mainloop() # invokes __getattr__!

As is, this script simply creates
Figure 7-23
again; changing
Example 7-25
to import this
extended
HelloPackage
from
gui7c
, though, produces the correctly-working
window in
Figure 7-24
.

Figure 7-24. A standalone class package in action

Routing attribute fetches to nested widgets works this way, but
that then requires even more extra coding in standalone package classes.
As usual, though, the significance of all these trade-offs varies per
application.

[
31
]
If you study the
tkinter
module’s source code (today, mostly in file
__init__.py
in
Lib\tkinter
), you’ll notice that many of
the attribute names it creates start with a single underscore to
make them unique from yours; others do not because they are
potentially useful outside of the tkinter implementation (e.g.,
self.master
,
self.children
). Curiously, at this writing
most of tkinter still does not use the Python “pseudoprivate
attributes” trick of prefixing attribute names with two leading
underscores to automatically add the enclosing class’s name and thus
localize them to the creating class. If tkinter is ever rewritten to
employ this feature, name clashes will be much less likely in widget
subclasses. Most of the attributes of widget classes, though, are
methods intended for use in client scripts; the single underscore
names are accessible too, but are less likely to clash with most
names of your own.

The End of the Tutorial

In this chapter, we learned the core concepts of Python/tkinter
programming and met a handful of simple widget objects along the way—e.g.,
labels, buttons, frames, and the packer geometry manager. We’ve seen
enough to construct simple interfaces, but we have really only scratched
the surface of the tkinter widget set.

In the next two chapters, we will apply what we’ve learned here to
study the rest of the tkinter library, and we’ll learn how to use it to
generate the kinds of interfaces you expect to see in realistic GUI
programs. As a preview and roadmap,
Table 7-1
lists the kinds of widgets we’ll meet
there in roughly their order of appearance. Note that this table lists
only widget classes; along the way, we will also
meet a few additional widget-related topics that don’t
appear in this table.

Table 7-1. tkinter widget classes

Widget
class

Description

Label

A simple
message area

Button

A simple
labeled push-button widget

Frame

A container for
attaching and arranging other widget
objects

Toplevel
,
Tk

A new
window managed by the window manager

Message

A
multiline label

Entry

A simple
single-line text-entry field

Checkbutton

A two-state
button widget, typically used for multiple-choice
selections

Radiobutton

A two-state button
widget, typically used for single-choice
selections

Scale

A slider
widget with scalable positions

PhotoImage

An image
object used for displaying full-color images on
other widgets

BitmapImage

An image
object used for displaying bitmap images on other
widgets

Menu

A set of
options associated with a
Menubutton
or top-level
window

Menubutton

A button
that opens a
Menu
of selectable options and submenus

Scrollbar

A control
for scrolling other widgets (e.g., listbox, canvas,
text)

Listbox

A list of
selection names

Text

A multiline
text browse/edit widget, with support for fonts, and
so on

Canvas

A graphic
drawing area, which supports lines, circles, photos,
text, and so on

We’ve already met
Label
,
Button
, and
Frame
in this chapter’s tutorial. To make the
remaining topics easier to absorb, they are split over the next two
chapters:
Chapter 8
covers the first
widgets in this table up to but not including
Menu
, and
Chapter 9
presents widgets that are lower
in this table.

Besides the widget classes in this table, there are additional
classes and tools in the tkinter library, many of which we’ll explore in
the following two chapters as well:

Geometry management

pack
,
grid
,
place

tkinter linked variables

StringVar
,
IntVar
,
DoubleVar
,
BooleanVar

Advanced Tk widgets

Spinbox
,
LabelFrame
,
PanedWindow

Composite widgets

Dialog
,
ScrolledText
,
OptionMenu

Scheduled callbacks

Widget
after
,
wait
, and
update
methods

Other tools

Standard dialogs, clipboard,
bind
and
Event
, widget configuration options,
custom and modal dialogs, animation techniques

Most tkinter widgets are familiar user interface devices. Some are
remarkably rich in functionality. For instance, the
Text
class implements a sophisticated multiline
text widget that supports fonts, colors, and special effects and is
powerful enough to implement a web browser’s page display. The similarly
feature-rich
Canvas
class provides
extensive drawing tools powerful enough for visualization and other
image-processing applications. Beyond this, tkinter extensions such as the
Pmw, Tix, and ttk packages described at the start of this chapter add even
richer widgets to a GUI programmer’s toolbox.

Python/tkinter for Tcl/Tk Converts

At the start
of this chapter, I mentioned that tkinter is Python’s
interface to the
Tk GUI library, originally written for the Tcl language. To
help readers migrating from Tcl to Python and to summarize some of the
main topics we met in this chapter, this section contrasts Python’s Tk
interface with Tcl’s. This mapping also helps make Tk references written
for other languages more useful to Python developers.

In general terms, Tcl’s command-string view of the world differs
widely from Python’s object-based approach to programming. In terms of Tk
programming, though, the syntactic differences are fairly small. Here are
some of the main distinctions in Python’s tkinter interface:

Creation

Widgets are created as class instance objects by calling a
widget class.

Masters (parents)

Parents are previously created objects that are passed to
widget-class constructors.

Widget options

Options are constructor or
config
keyword arguments or indexed
keys.

Operations

Widget operations (actions) become tkinter widget class object
methods.

Callbacks

Callback handlers are any callable objects: function, method,
lambda, and so on.

Extension

Widgets are extended using Python class inheritance
mechanisms.

Composition

Interfaces are constructed by attaching objects, not by
concatenating names.

Linked variables (next chapter)

Variables associated with widgets are tkinter class objects
with methods.

In Python, widget creation commands (e.g.,
button
) are Python class names that start with
an uppercase letter (e.g.,
Button
),
two-word widget operations (e.g.,
add
command
) become a single method name with
an underscore (e.g.,
add_command
), and
the “configure” method can be abbreviated as “config,” as in Tcl. In
Chapter 8
, we will also see that tkinter
“variables” associated with widgets take the form of class instance
objects (e.g.,
StringVar
,
IntVar
) with
get
and
set
methods, not simple Python or Tcl variable names.
Table 7-2
shows some of the primary language
mappings in more concrete terms.

Table 7-2. Tk-to-tkinter mappings

Operation

Tcl/Tk

Python/tkinter

Creation

Frame .panel

panel =
Frame()

Masters

button
.panel.quit

quit =
Button(panel)

Options

button .panel.go -fg
black

go = Button(panel,
fg='black')

Configure

.panel.go config -bg
red

go.config(bg='red')
go['bg'] = ‘red’

Actions

.popup
invoke

popup.invoke()

Packing

pack .panel -side left
-fill x

panel.pack(side=LEFT,
fill=X)

Some of these differences are more than just syntactic, of course.
For instance, Python builds an internal widget object tree based on parent
arguments passed to widget constructors, without ever requiring
concatenated widget pathname strings. Once you’ve made a widget object,
you can use it directly by object reference. Tcl coders can hide some
dotted pathnames by manually storing them in variables, but that’s not
quite the same as Python’s purely object-based model.

Once you’ve written a few Python/tkinter scripts, though, the coding
distinctions in the Python object world will probably seem trivial. At the
same time, Python’s support for object-oriented techniques adds an
entirely new component to Tk development; you get the same widgets, plus
Python’s support for code structure and reuse.

Other books

False Angel by Edith Layton
Allure Magnified by Blanco, N Isabelle
The Love Letter by Matthews, Erica
Shadows of the Past by Brandy L Rivers
Tattoo Thief (BOOK 1) by Heidi Joy Tretheway
The Secret Journey by James Hanley
Me and My Hittas by Tranay Adams
Attack of the Amazons by Gilbert L. Morris


readsbookonline.com Copyright 2016 - 2024