Popcorn Dave has asked for the wisdom of the Perl Monks concerning the following question:

Fellow monks,
I have yet another Tk question yatkq? :) for those wiser and more experienced than I.

I've finished my interface and I've got two entry widgets on it. I'm perplexed why the -textvariable is not getting or replacing a value.

My code follows:

my $reg=$top->Entry(width=>30, -font=>12, -textvariable=>\$regex, )->pack();

My understanding from Mastering Perl/Tk was that it should be put in there and accessable as $regex. Right or wrong? Do I need to be doing something else to pass the information?

Many thanks to all for the help!

Replies are listed 'Best First'.
Re: Question on Tk Entry
by graff (Chancellor) on Apr 22, 2002 at 04:14 UTC
    The following seems to work for me -- even though I left out important things like "use strict;" (I wanted to make a worst-case scenario ;^). So the trick for you is to figure out what you're doing that's different.

    This is the whole program: it puts up an Entry and a Button; when you push the button, it prints whatever is in the entry at that moment. See if it does that for you.

    use Tk; $main=MainWindow->new(); $main->Entry(-width => 20, -textvariable => \$regex, )->pack(); $main->Button(-text=>"Print me", -command => sub{ print "$regex\n" } )->pack(); MainLoop;
      Thank you for that. I realized after seeing your code that I can do that for my code. I've got two entry lines and I will have the user click the button so I can get them then.

      As I put in my amendment however, is there a way to do this without using the button(-command=>) approach?

      Thanks again!

Re: Question on Tk Entry
by Popcorn Dave (Abbot) on Apr 22, 2002 at 04:15 UTC
    Let me make one amendment to my query.

    I was just checking the Perl/Tk FAQ and there is an example there close to what I want to do, but I don't want to have the user click a button to get their input in to my variable and there seems to be no -command or similar for Entry to run a subroutine, so now I'm really stumped...

      You're on the right track here. The -textvariable is getting assigned by Tk any time the user interacts with your Entry widget, but you just need to decide how and when you want to access that variable. If I understand correctly, you'd like to get at it when the user leaves the field rather than having the user click a button. In this case, you should use the -validatecommand option, which can essentially act as the -command option you were using on the button. This is similar to the binding approach that graff mentions, but it will trigger any time the Entry widget loses focus, not just when the user hits enter. Give this a whirl:
      #!c:/perl/bin/perl -w use strict; use Tk; my $regex = ''; my $foo = ''; my $main=MainWindow->new(); $main->Entry( -width => 20, -textvariable => \$regex, -validate => 'focusout', -validatecommand => sub{ print "Regex: $regex\n" }, )->pack(); $main->Entry( -width => 20, -textvariable => \$foo, -validate => 'focusout', -validatecommand => sub{ print "Foo: $foo\n" }, )->pack(); MainLoop;

      -- grummerX

      Oh, well that's something different. So, is it okay for you if the user hits the "return" key (aka "Enter") to indicate that the string in the Entry is now finished? (The user will probably have to do something to signal that their done typing.) In that case, try adding this somewhere in your code after declaring the Entry widgets:

      $top->bind( 'Tk::Entry', '<Enter>', \&your_subroutine );

      I suppose if you wanted the subroutine to be triggered on every keystroke, so you could see each key as it's typed, you could try:

      $top->bind( 'Tk::Entry', '<KeyRelease>', [\&subroutine, Ev('K')] );

      In this case, the subroutine gets the keystroke value as the second argument (first arg is the reference to the entry widget that got the event).

        That looks a bit more like what I was after originally, but I think I'm going to stick with the button as there is no guarentee that the user would actually hit the enter key and not just move on.
Re: Question on Tk Entry
by {NULE} (Hermit) on Apr 22, 2002 at 16:57 UTC
    Hi Popcorn Dave,

    From reading through this thread I thought it was important to make a distinction. Since Tk is event driven you need to specify an event during which your variable is read. One way of doing this is using a polling function. This example displays the contents of $var every second:

    #! /usr/local/bin/perl -w use strict; use Tk; my $var = ''; my $w = new MainWindow; $w->Entry( -textvariable => \$var )->pack; $w->repeat(1000, [ \&print_var, \$var ] ); MainLoop; sub print_var { my $var = shift; print scalar(localtime)," >$$var\n"; }
    This is somewhat inelegant because it is called no matter whether your variable has changed or not.

    Another thing you may want to play with (I've not had much luck with it) is to use the validate option on your entry widget.

    #! /usr/local/bin/perl -w use strict; use Tk; my $var2 = ''; my $w = new MainWindow; $w->Entry( -validate => 'all', -validatecommand => [ \&print_var, \$va +r2 ], -textvariable => \$var2 )->pack; MainLoop; sub print_var { my $var = shift; print scalar(localtime)," >$$var\n"; }
    This basically says that with any action that affects the entry widget perform the validation callback.

    Update: I almost forgot to mention - it may be imperitive that you pass a reference to your callback subroutine, particularly with after or repeat. Otherwise they will print out your initial value forever.

    Good luck, I hope this helps.
    {NULE}
    --
    http://www.nule.org