in reply to Entry widget questions

My advice? Drop that #2 requirement right now.

Humans are not machines. Humans have interruptions, humans think out of order, humans don't like it when they have no choices.

What if they just were looking for some other feature, but now they're trapped? What if they don't know what a MAC address is? What if they know it, but remembered that they need to do something else first?

The #3 requirement should serve well enough to fit your intention. If the MAC is invalid when they try to COMMIT their new entry, then you can rightfully balk. Until then, let them do whatever they want to do with the widgets.

Separately, I am not a fan of string-of-pearls input widgets. Dotted Four IP addresses, MAC addresses, credit card numbers, social security numbers, phone numbers, etc. If you feel you have to "automate" the Tab key because there are so many fields, then you have clearly been thinking the wrong direction. Offer one field with much smarter validation. Let computers do what computers are good at, but give humans a human interface. If that's not enough to convince you, how would you "cut" or "paste" a full MAC address with this scheme?

--
[ e d @ h a l l e y . c c ]

Replies are listed 'Best First'.
Re^2: Entry widget questions
by ambrus (Abbot) on Feb 15, 2007 at 20:54 UTC

    Very true.

      Helley's comments are why I hate working on GUIs. Not to mention the huge time sink they are. I thought this would take me a couple hours and 20 lines of code, it's taking a couple days and a couple pages of code.

      This is just a first cut. Once we're happy things are working right I'm replacing the tk entry widget with some sort of database query to get the MAC address (we build 100+ of these things a week). But the database server won't be available until sometime this summer, I have to start programming MACs Monday.

      My current script is below. It's still got bugs, but to be honest I've spent a lot more time on it than I ever thought it would take.

      #!perl -w # # Perl/tk script to present the user with the existing MAC address, an +d # allow them to enter a new one. # # Known bugs. # 1) Make an invalid entry '333', and tab. You go to the next field. # 2) I've seen the background stay red. Not sure how I do it, but on +ce it # goes red it stays red. use strict; use MyPerlConstants; use Tk; # Take a 6 element array and make it string. sub makeString { my @data = @_; my $result = sprintf "%02s:%02s:%02s:%02s:%02s:%02s", $data[0], $data[1], $data[2], $data[3], $data[4], $data +[5]; return $result; } my $debug = $TRUE; # If the user control-C's out, or kills my window, this will stay fals +e my $done = $FALSE; # I want the first widget to have focus when I start, the only way I'v +e # managed to do so is to save all my entry widgets. my @entries; # Turns out it's useful to know what entry your on.... my $current = 0; sub validate { my ($val) = @_; my $b_valid = ($val =~ /^[0-9a-f]{1,2}$/i)? 1: 0; # debugging, print the field. printf"<%s>: %s valid\n", $val, $b_valid? "IS": "is NOT" if $debu +g; whoopsie() if !$b_valid; if($b_valid) { $current++; $current = 0 if $current > 5; } #$entries[$current]->focus(); return $b_valid; } # Called when the user makes an invalid entry. sub whoopsie { my $widget = $entries[$current]; my $bg = $widget->cget(-background); $widget->bell; $widget->configure(-background => 'red'); $widget->update(); $widget->after(500, sub { $widget->configure(-background => $bg) } +); $widget->selectionFrom(0); $widget->selectionTo(100); $widget->focus(); #$widget->selectionRange(0, 3); } sub doit { my @addy = @_; my $mw = MainWindow->new(-title => 'MAC Address Input'); # 3 frames: original, new, and the buttons. my $forig = $mw->Frame()->pack(-expand => 1, -fill => 'both')-> pack(-side => 'top'); my $fnew = $mw->Frame()->pack(-expand => 1, -fill => 'both')-> pack(-side => 'top'); my $fdone = $mw->Frame()->pack(-expand => 1, -fill => 'both')-> pack(-side => 'top'); $forig->Label(-text => 'Current MAC address ', -width => 20)-> pack(-side => 'left'); $fnew->Label(-text => 'Enter new MAC address ', -width => 20)-> pack(-side => 'left'); # Now build some entry widgets to change it. for my $i (0 .. 5) { $forig->Label(-text => $addy[$i], -width => 2, -takefocus => 0) ->pack(-side => 'left'); # Don't add a trailing colon (jeez, the mental image that brings +....) if($i != 5) { $forig->Label(-text => ':', -width => 1)->pack(-side => 'left +'); } $entries[$i] = $fnew->Entry( -textvariable => \$addy[$i], -width => 2, -validate => 'focusout', -validatecommand => \&validate, #-invalidcommand => [ \&whoopsie, $entries[$i] ], )->pack(-side => 'left'); if($i != 5) { $fnew->Label(-text => ':', -width => 1)->pack(-side => 'left' +); } } $entries[0]->focus; # give first widget focus. $entries[0]->selectionFrom(0); $entries[0]->selectionTo(100); $fdone->Label(-width => 12)->pack(-side => 'left'); $fdone->Label(-width => 12)->pack(-side => 'right'); $fdone->Button(-text => "Program", -command => sub {$mw->destroy;$done = $TRUE}, -background => 'green', -activebackground => 'green2', )->pack(-side => 'left'); $fdone->Button(-text => "Cancel", -command => sub {$mw->destroy;}, -background => 'red', -activebackground => 'red2', )->pack(-side => 'right'); MainLoop; return(@addy); } #my @foo = (0x10, 0x22, 0x33, 0x4b, 0x5f, 0x6d); my @foo = qw/10 22 33 4b 5f 6d/; print "Starting with: " . makeString(@foo) . "\n"; my @bar = doit(@foo); print "Ended with: " . makeString(@bar) . "\n"; print 'done: ' . $done . "\n";
      Anyway, thanks for your help, and I'm sure you'll see some of your DNA in this script.

      I'd actually enjoy any critique of this code you might write up. As I said, I'm new to this and would rather not unlearn bad habits in a few months. My email is jharkins@qualcomm.com if you want to critique it privately.