Read Programming Python Online

Authors: Mark Lutz

Tags: #COMPUTERS / Programming Languages / Python

Programming Python (60 page)

BOOK: Programming Python
2.31Mb size Format: txt, pdf, ePub
ads
Message and Entry

The
Message
and
Entry
widgets
allow for display and input of simple text. Both are
essentially functional subsets of the
Text
widget we’ll meet later;
Text
can do everything
Message
and
Entry
can, but not vice versa.

Message

The
Message
widget is
simply a place to display text. Although the standard
showinfo
dialog we met earlier is
perhaps a better way to display pop-up messages,
Message
splits up long strings automatically
and flexibly and can be embedded inside container widgets any time you
need to add some read-only text to a display. Moreover, this widget
sports more than a dozen configuration options that let you customize
its appearance.
Example 8-16
and
Figure 8-21
illustrate
Message
basics, and demonstrates how
Message
reacts to horizontal stretching
with
fill
and
expand
; see
Chapter 7
for more on resizing and Tk or
tkinter references for other options
Message
supports.

Example 8-16. PP4E\Gui\tour\message.py

from tkinter import *
msg = Message(text="Oh by the way, which one's Pink?")
msg.config(bg='pink', font=('times', 16, 'italic'))
msg.pack(fill=X, expand=YES)
mainloop()

Figure 8-21. A Message widget at work

Entry

The
Entry
widget is a
simple, single-line text input field. It is typically used
for input fields in form-like dialogs and anywhere else you need the
user to type a value into a field of a larger display.
Entry
also supports advanced concepts such as
scrolling, key bindings for editing, and text selections, but it’s
simple to use in practice.
Example 8-17
builds the input
window shown in
Figure 8-22
.

Example 8-17. PP4E\Gui\tour\entry1.py

from tkinter import *
from quitter import Quitter
def fetch():
print('Input => "%s"' % ent.get()) # get text
root = Tk()
ent = Entry(root)
ent.insert(0, 'Type words here') # set text
ent.pack(side=TOP, fill=X) # grow horiz
ent.focus() # save a click
ent.bind('', (lambda event: fetch())) # on enter key
btn = Button(root, text='Fetch', command=fetch) # and on button
btn.pack(side=LEFT)
Quitter(root).pack(side=RIGHT)
root.mainloop()

Figure 8-22. entry1 caught in the act

On startup, the
entry1
script
fills the input field in this GUI with the text “Type words here” by
calling the widget’s
insert
method.
Because both the Fetch button and the Enter key are set to trigger the
script’s
fetch
callback function,
either user event gets and displays the current text in the input field,
using the widget’s
get
method:

C:\...\PP4E\Gui\Tour>
python entry1.py
Input => "Type words here"
Input => "Have a cigar"

We met the

event
earlier when we studied
bind
; unlike
button presses, these lower-level callbacks get an event argument, so
the script uses a lambda wrapper to ignore it. This script also packs
the entry field with
fill=X
to make
it expand horizontally with the window (try it out), and it calls the
widget
focus
method to give the entry
field input focus when the window first appears. Manually setting the
focus like this saves the user from having to click the input field
before typing. Our smart Quit button we wrote earlier is attached here
again as well (it verifies exit).

Programming Entry widgets

Generally speaking, the
values typed into and displayed by
Entry
widgets are set and fetched with
either tied “variable” objects (described later in this chapter) or
Entry
widget method calls such as
this one:

ent.insert(0, 'some text')          # set value
value = ent.get() # fetch value (a string)

The first parameter to the
insert
method gives the position where the
text is to be inserted. Here, “0” means the front because offsets
start at zero, and integer
0
and
string
'0'
mean the same thing
(tkinter method arguments are always converted to strings if needed).
If the
Entry
widget might already
contain text, you also generally need to delete its contents before
setting it to a new value, or else new text will simply be added to
the text already present:

ent.delete(0, END)                  # first, delete from start to end
ent.insert(0, 'some text') # then set value

The name
END
here is a
preassigned tkinter constant denoting the end of the widget; we’ll
revisit it in
Chapter 9
when we
meet the full-blown and multiple-line
Text
widget (
Entry
’s more powerful cousin). Since the
widget is empty after the deletion, this statement sequence is
equivalent to the prior one:

ent.delete('0', END)                # delete from start to end
ent.insert(END, 'some text') # add at end of empty text

Either way, if you don’t delete the text first, new text that is
inserted is simply added. If you want to see how, try changing the
fetch
function in
Example 8-17
to look like
this—an “x” is added at the beginning and end of the input field on
each button or key press:

def fetch():
print('Input => "%s"' % ent.get()) # get text
ent.insert(END, 'x') # to clear: ent.delete('0', END)
ent.insert(0, 'x') # new text simply added

In later examples, we’ll also see the
Entry
widget’s
state='disabled'
option, which makes it read
only, as well as its
show='*'
option, which makes it display each character as a
*
(useful for password-type inputs). Try
this out on your own by changing and running this script for a quick
look.
Entry
supports other options
we’ll skip here, too; see later examples and other resources for
additional
details.

Laying Out Input Forms

As mentioned,
Entry
widgets
are often used to get field values in form-like displays.
We’re going to create such displays often in this book, but to show you
how this works in simpler terms,
Example 8-18
combines labels,
entries, and frames to achieve the multiple-input display captured in
Figure 8-23
.

Example 8-18. PP4E\Gui\Tour\entry2.py

"""
use Entry widgets directly
lay out by rows with fixed-width labels: this and grid are best for forms
"""
from tkinter import *
from quitter import Quitter
fields = 'Name', 'Job', 'Pay'
def fetch(entries):
for entry in entries:
print('Input => "%s"' % entry.get()) # get text
def makeform(root, fields):
entries = []
for field in fields:
row = Frame(root) # make a new row
lab = Label(row, width=5, text=field) # add label, entry
ent = Entry(row)
row.pack(side=TOP, fill=X) # pack row on top
lab.pack(side=LEFT)
ent.pack(side=RIGHT, expand=YES, fill=X) # grow horizontal
entries.append(ent)
return entries
if __name__ == '__main__':
root = Tk()
ents = makeform(root, fields)
root.bind('', (lambda event: fetch(ents)))
Button(root, text='Fetch',
command= (lambda: fetch(ents))).pack(side=LEFT)
Quitter(root).pack(side=RIGHT)
root.mainloop()

Figure 8-23. entry2 (and entry3) form displays

The input fields here are just simple
Entry
widgets. The script builds an explicit
list of these widgets to be used to fetch their values later. Every time
you press this window’s Fetch button, it grabs the current values in all
the input fields and prints them to the standard output stream:

C:\...\PP4E\Gui\Tour>
python entry2.py
Input => "Bob"
Input => "Technical Writer"
Input => "Jack"

You get the same field dump if you press the Enter key anytime
this window has the focus on your screen; this event has been bound to
the whole root window this time, not to a single input field.

Most of the art in form layout has to do with arranging widgets in
a hierarchy. This script builds each label/entry row as a new
Frame
attached to the window’s current
TOP
; fixed-width labels are attached
to the
LEFT
of their row, and entries
to the
RIGHT
. Because each row is a
distinct
Frame
, its contents are
insulated from other packing going on in this window. The script also
arranges for just the entry fields to grow vertically on a resize, as in
Figure 8-24
.

Figure 8-24. entry2 (and entry3) expansion at work

Going modal again

Later on this tour, we’ll see how to make similar form layouts
with the
grid
geometry
manager, where we arrange by row and column numbers instead of frames.
But now that we have a handle on form layout, let’s see how to apply
the modal dialog techniques we met earlier to a more complex input
display.

Example 8-19
uses
the prior example’s
makeform
and
fetch
functions to generate a form
and prints its contents, much as before. Here, though, the input
fields are attached to a new
Toplevel
pop-up window created on demand,
and an OK button is added to the new window to trigger a window
destroy event that erases the pop up. As we learned earlier, the
wait_window
call pauses until the
destroy happens.

Example 8-19. PP4E\Gui\Tour\entry2-modal.py

# make form dialog modal; must fetch before destroy with entries
from tkinter import *
from entry2 import makeform, fetch, fields
def show(entries, popup):
fetch(entries) # must fetch before window destroyed!
popup.destroy() # fails with msgs if stmt order is reversed
def ask():
popup = Toplevel() # show form in modal dialog window
ents = makeform(popup, fields)
Button(popup, text='OK', command=(lambda: show(ents, popup))).pack()
popup.grab_set()
popup.focus_set()
popup.wait_window() # wait for destroy here
root = Tk()
Button(root, text='Dialog', command=ask).pack()
root.mainloop()

When you run this code, pressing the button in this program’s
main window creates the blocking form input dialog in
Figure 8-25
, as
expected.

Figure 8-25. entry2-modal (and entry3-modal) displays

But a subtle danger is lurking in this modal dialog code:
because it fetches user inputs from
Entry
widgets embedded in the popped-up
display, it must fetch those inputs
before
destroying the pop-up window in the OK press callback handler. It
turns out that a
destroy
call
really does destroy all the child widgets of the window destroyed;
trying to fetch values from a destroyed
Entry
not only doesn’t work, but also
generates a traceback with error messages in the console window. Try
reversing the statement order in the
show
function to see for yourself.

To avoid this problem, we can either be careful to fetch before
destroying, or use tkinter variables, the subject of the
next section.

BOOK: Programming Python
2.31Mb size Format: txt, pdf, ePub
ads

Other books

Friday's Child by Kylie Brant
Longhorn Country by Tyler Hatch
Hall of Small Mammals by Thomas Pierce
Catch Me by Lorelie Brown
The Tantric Principle by Probst, Jennifer
Shy by Grindstaff, Thomma Lyn
The Caveman by Jorn Lier Horst
Love, Stargirl by Jerry Spinelli


readsbookonline.com Copyright 2016 - 2024