Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Finding the widget name which generated an event

2 views
Skip to first unread message

Python-lover

unread,
May 6, 2003, 6:31:42 AM5/6/03
to
Hi,
how can i find the widget name that generated an
event? I have placed 2 entry widgets in my window and
bind "FocusIn","FocusOut" events to those entry boxes.
In the event handler i want to print the name of the
entry widget that generated the event. I tried with
event.widget. But i got an instance number of the
widget rather than widget name. How can i get the
widget name that generated an event?
My coding is given below.

import Tkinter
def gotFocus(event):
print 'Focus in',' Widget: ',event.widget
def lostFocus(event):
print 'Focus out',' Widget: ',event.widget

root = Tkinter.Tk()

e = Tkinter.Entry()
e1=Tkinter.Entry()

e.bind('<FocusIn>', gotFocus)
e.bind('<FocusOut>', lostFocus)
e1.bind('<FocusIn>', gotFocus)
e1.bind('<FocusOut>', lostFocus)
e.pack()
e1.pack()
root.mainloop()

Thanx

__________________________________
Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo.
http://search.yahoo.com

Jeff Epler

unread,
May 6, 2003, 8:11:45 AM5/6/03
to
What do you mean by "the name" of a widget?

If you mean, "I want to see the string 'e' or the string 'e1'", then you're
barking up the wrong tree. If "the name" of the widget is the name of the
global variable identical to the widget, then what would it be if you wrote
e = f = Tkinter.Entry()
? What if there's no name for the widget because it's part of a
non-collectable but unreachable cycle? You really don't want to think
about things in this way, trust me.

If you want to "do something" to the entry in the event, just call widget
methods on event.widget. For instance:
def gotFocus(event):
event.widget.configure(bg="blue", fg="white")
def lostFocus(event):
event.widget.configure(bg="white", fg="black")

Jeff

Jeff Epler

unread,
May 6, 2003, 10:34:15 AM5/6/03
to
I don't see why you don't use two functions. If some part of the work
is common (which it isn't in your above example) then just call the
common function.

If you really insist on using this approach, you can use 'is' to check
whether it's one widget or the other:
def validity_check(event):
common stuff
if event.widget is First:
do string validation for 1st entrywidget
else if entry.widget is Second:
do integer validation for 2nd entrywidget
other common stuff

but you'll quickly find that this becomes unmanagable as you add widgets.

The alternative is
def string_validity_check(event):
common_stuff()
do string validation for event.widget
other_common_stuff()

def int_validity_check likewise

e.bind("<FocusOut>", string_validity_check)
f.bind("<FocusOut>", int_validity_check)

You could also use subclassing to validate different types of widgets.

class ValidatedEntry(Tkinter.Entry):
def __init__(self, *args, **kw):
Tkinter.Entry.__init__(*args, **kw)
self.bind("<FocusOut>", self.validity_check)

def common_stuff(self): pass
def other_common_stuff(self): pass

class StringEntry(ValidatedEntry):
def validity_check(self, event):
self.common_stuff()
do string validation for self / event.widget (they are the same)
self.other_common_stuff()

Using FocusOut to perform validation has one other drawback that I
should mention: you'll see a <FocusOut> event not only when the user
presses Tab or clicks on another field, but also if she switches to a
different application (which may be done before the input is "complete",
for instance if she wants to refer to a value in a different window in
choosing the value to enter here). In one software package I worked on
it was decided that when the user left a field and it didn't validate,
a dialog would be shown telling her the valid range of values. This led
to piles of problems, because showing the dialog would cause another
<FocusOut> event! To make this work properly, we ended up replacing
almost all of the focus- and traversal-related machinery that Tk provides,
and there are still probably bugs---it's certainly less maintainable.
Even just writing
if not contents_valid(event.widget):
# move focus back to a widget when its contents are invalid
event.widget.focus()
can lead to grief: imagine the other widget selected was *also* invalid.
Now you'll have a tug-of-war for keyboard focus from which the program
will likely never recover.

That leaves only passive actions for invalid entry contents.
For instance, you could choose to color the background read (instead
of white or grey) when the contents of a field are not valid. But I
don't know of any user interface guide that recommends this practice.
For starters, you don't know in advance what the user's color scheme is,
and I don't think any major UI standard defines an "alert" background
color---so, by coloring the background red you might decrease or destroy
the visual contrast between the foreground and background of the widget.

I consulted 2 of the 3 user interface guides I usually refer to and I
didn't immediately find a section discussing ways to inform the user
that entered information is incorrect (Galitz' "It's Time to Clean Your
Windows" and Johnson's "GUI Bloopers" -- I also usually refer to the
Microsoft Windows User Experience book, but it's out of my office right
now) so either I looked past it in the index or this isn't a problem
with an accepted solution.

(and let me say that, even as a Unix bigot, that MWUE seems to contain
a fair amount of good advice on creating a consistent user interface,
though it's interspersed with "rules for anal-retentive win32 application
creators" such as the minimum and maximum dialog size in "DLUs". I
can't recommend enough that, if you're going to design user interfaces,
you educate yourself about what good user interface is)

Jeff Epler
jep...@unpythonic.net

0 new messages