Richard Suchenwirth 2002-03-13: Here is a little proc that brings up a username/password widget, the password field being made unreadable as is usual, and grabs focus until terminated with "OK", "Cancel" or <Return>.
It returns a list of two elements: username and password, or an empty list if canceled.
Description edit
Much can be done to improve this - just take it as a first shot!
proc tk_login {w {title "Log please"}} {
toplevel $w -borderwidth 10
wm title $w $title
label $w.u -text "User name:"
entry $w.user -textvar _username
label $w.p -text "Password:"
entry $w.pass -show * -textvar _password
label $w.dummy -text ""
button $w.ok -text OK -command {set _res [list $_username $_password]}
button $w.cancel -text Cancel -command {set _res {}}
grid $w.u $w.user - -sticky wns
grid $w.p $w.pass - -sticky wns
grid $w.dummy x x
grid x $w.ok $w.cancel -sticky news
bind $w <Return> [list $w.ok invoke]
bind $w <Escape> [list $w.cancel invoke]
raise $w
grab set $w
vwait _res
destroy $w
unset ::_username ::_password
return $::_res
}
# Silly little test...
pack [text .t]
update
set password ""
while {$password != "secret"} {
set userpass [tk_login .login]
set password [lindex $userpass 1]
}
.t insert end "[lindex $userpass 0] logged in\n"
KPV: Here's a slight tweak of the above code to get better resize behavior. Of course, you could just make the windows un-resizable but I think it's better to allow it to get wider. Also, there's no need for the dummy label widget to get the spacing you want--just use
grid to create an empty row with
-minsize set.
proc tk_login2 {w {title "Login please"}} {
toplevel $w -borderwidth 10
wm title $w $title
# change the following to 'wm resizable $w 0 0' to prevent resizing
wm resizable $w 1 0
wm protocol $w WM_DELETE_WINDOW {set _res {}}
label $w.u -text "User name:"
entry $w.user -textvar _username
label $w.p -text "Password:"
entry $w.pass -show * -textvar _password
button $w.ok -text OK -width 8 -command {set _res [list $_username $_password]}
button $w.cancel -text Cancel -width 8 -command {set _res {}}
grid $w.u $w.user - - -sticky news
grid $w.p $w.pass - - -sticky news
grid rowconfigure $w 10 -minsize 20
grid x x $w.ok $w.cancel -sticky news -row 11 -padx 2 -pady 2
grid columnconfigure $w 1 -weight 1
bind $w <Return> [list $w.ok invoke]
bind $w <Escape> [list $w.cancel invoke]
raise $w
grab set $w
focus $w.user
vwait _res
destroy $w
unset ::_username ::_password
return $::_res
}
Scott Nichols: I like this login window. I tweaked the above to set focus on the user entry.
RLH: Gave the buttons a uniform width and padding to make them look better.
rdt: Well, the problem that I see with this, is that reducing the size covers the buttons instead of using the left-side space. To me, this is real no-no!
RLH: I just re-ran the second version and it looks better. The original has the buttons side-by-side, a ui design no-no. The second one spaces them and makes the buttons uniform in size. I guess I do not see your point.
rdt: Now that it's resizable, reduce its size from the beginning value. The Cancel button gets truncated! A no-no!
RLH: I agree and disagree. I agree that truncating the buttons is a no-no. I disagree because the original change states that you could make the dialog "un-resizable" to prevent that, which is what I would do for a login dialog. So I was not thinking about resizing only aesthetics.
rdt: I understand. If its made resizable in order that the entry boxes can be made larger, then the resizing should _never_ truncate a button.
RLH: No argument from me there.
RS 2004-09-14: Added a line each to unset ::_username and ::_password...
LV: So what could be added to the second login to keep it from being resized so small that the buttons disappear?
JJ: Added keybinding for <Escape> to both examples
EF: Added a wm protocol tweak to make sure closing the window is the same as pressing cancel.
See Also edit
- Authentication by formula
- tk login window