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

Hi. I got some code from this site that demonstrates "-textvariable" usage. However, there are some basic questions I have about it's operation. The code is;

#!/usr/bin/perl use strict; use warnings; use Tk; use POSIX; my $red; my $green; my $blue; my $mw = MainWindow->new; $mw->geometry('300x100'); # x amount then y amount $mw->title('Raw Renamer'); # A frame for labels on the left hand size my $left_frame = $mw->Frame (-borderwidth => 2, -relief => 'groove') ->pack(-side => 'left', -anchor => 'n', -expand => 1); my $text_label = $left_frame->Label->pack(-side => 'left', # Why + this ? -anchor => 'n', -expand => 1); $text_label->Label(-text =>"Red")->pack( -side => 'top', -anchor => 'w'); $text_label->Label(-text =>"Green")->pack(-side => 'top', -anchor => 'w'); $text_label->Label(-text =>"Blue")->pack( -side => 'top', -anchor => 'w'); # Another frame for the ($red $green $blue) variables my $variable_frame = $mw->Frame (-borderwidth => 4, -relief => 'groove +') ->pack(-side => 'left', -anchor => 'n', -expand => 1); my $red_label = $variable_frame->Label(-textvariable =>\$red) ->pac +k(-side => 'top'); my $green_label = $variable_frame->Label(-textvariable =>\$green)->pac +k(-side => 'top'); my $blue_label = $variable_frame->Label(-textvariable =>\$blue) ->pac +k(-side => 'top'); Intialize(); # How is this infinite loop bypassed ? MainLoop; sub Intialize { print "Str"; while(1) { print "."; $red = floor(50*rand()); $red_label->update; sleep 2; $green = floor(50*rand()+50); $green_label->update; sleep 2; $blue = floor(50*rand()+100); $blue_label->update; sleep 2; } }

The line "my $text_label" seems to be half a declaration that is used in an anonymous fashion in the subsequent 3 labels. Is this the case ?. I tried removing the "pack" part expecting that this is not required. But it is required.

Next, the call "Intialize();" should get stuck in an infinite loop. But it does not and the program runs OK? and the "MainLoop;" gives a display screen.

Regard JC.......

Replies are listed 'Best First'.
Re: Basic questions of Tk programming
by haj (Vicar) on Jan 23, 2025 at 13:01 UTC

    When you use Tk; the library sets up an environment which is able to wait for events. It does not start the event loop until your program hands over control, which you are supposed to do with MainLoop;

    Calling sleep has the same effect: It hands over control. Tk paints the screen and ... waits. It does not get any events, though. Instead, your Initialize routine wakes up and continues, happy to use the Tk screen. The program use the Tk screen drawing capability, but not the Tk event loop.

    This is an infinite loop: The call to MainLoop; never happens. You'll notice that there is an error message when you close the window:

    Usage $widget->update(...)
    Tk::Label=HASH(0x5f5632326bd8) is not a Tk object at jmclifford.pl line 56.
      Hello haj and bravo,

      when I read your reply it made sense. I was surprised to read:

      > Calling sleep has the same effect: It hands over control. Tk paints the screen and ... waits. It does not get any events, though. Instead, your Initialize routine wakes up and continues, happy to use the Tk screen. The program use the Tk screen drawing capability, but not the Tk event loop. So should be pack geometry manager to draw the screen.This can be reduced to:

      ## BAD CODE !! use strict; use warnings; use Tk; my $number = 1; my $mw = MainWindow->new; my $label = $mw->Label(-textvariable =>\$number)->pack(); # sleep 5; MainLoop; while (1){ $number++; $label->update; sleep 1;}

      ..without the never called MainLoop

      By other hand, uncommenting the sleep 5; MainLoop; line pack does not draw the screen, so the screen drawing capability cannot be proved by me.

      For sure is buggy code, but can be useful to inspect the internal machineries of Tk

      The error: Tk::Label=HASH(0x39a2828) is not a Tk object at textlabel_reduced.pl line 11. only shows closing the the program with the X but no sending CTRL-C in the console.

      A final note: perlmonks is the last place on earth (<- thanks to English native ;) last remaining place on earth to get support on perl Tk :)

      L*

      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

        It's not the sleep that draws the screen, it's the ->update!

        "A final note: perlmonks is the last place on earth to get support on perl Tk :)"
        This makes my sad. I think I have been quite helpful.

        "A final note: perlmonks is the last place on earth to get support on perl Tk :)"

        Perhaps this is lost in translation, while not a Tk user myself I do see Tk threads reasonably often with much help & advice given. For clarity, by the statement above do you mean that once someone posts here they don't go anywhere else for Tk help?

Re: Basic questions of Tk programming
by tybalt89 (Monsignor) on Jan 23, 2025 at 16:48 UTC

    YUCK! That's some horrible code you found.

    The $text_label should be a Frame, not a Label. The whole 'Intialize' should be redone with ->repeat.

    Here's how I would do the spirit of this program.

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11163827 use warnings; use Tk; my ($red, $green, $blue) = (0, 50, 100); my %colorhash = (Red => \$red, Green => \$green, Blue => \$blue); my $mw = MainWindow->new; $mw->geometry( '300x100+500+400' ); my $row = 1; for ( qw( Red Green Blue ) ) { $mw->Label(-text => $_, )->grid(-row => $row, -column => 1, -sticky => 'w'); $mw->Label(-textvariable => $colorhash{$_}, )->grid(-row => $row++, -column => 2, -sticky => 'e'); } my $color = 0; $mw->repeat( 1000, \&change ); $mw->repeat( 1777, sub {-M $0 < 0 and exec $0}); # restart when code c +hanges MainLoop; sub change { ( sub { $red = int rand 50 }, sub { $green = 50 + int rand 50 }, sub { $blue = 100 + int rand 50 } )[ $color = ( $color + 1 ) % 3 ](); }

      Hi. A great response by all. And thanks for the re-write of the code (tybalt89). I appreciated all of this except for the "# restart when code changes" line.

      It can be a problem when you suspect you are missing key issues for bad code.

      Regards JC......

Re: Basic questions of Tk programming -- updated
by Discipulus (Canon) on Jan 23, 2025 at 12:32 UTC
    Hello jmClifford,

    the MainLoop as I understand it, takes the control of all events in your program, in a higher position, as Tk programs are event driven so I suppose ( WRONG supposition, see haj's reply)(and I'm bit surprised by your while 1 loop working ok) that when the MainLoop schedules events your while 1 loop falls into the category of idle events (to be confirmed) after windows, files and timers ones (in this order).

    Infact when you realize that you are already inside an infinite loop seems weird to put in another one inside the main. General practice is to use Tk::after's after and repeat utilities.

    About my $text_label ..I must admit I do not fully understand your sentence, but, for me you are declaring a variable and when you pack the MainLoop draws it on the screen, then you reuse the same variable to hold something else and you draw... it works but for me is misleading and bug prone. Just name 3 variables:

    my $text_label_GREEN = $left_frame->Label->pack(... my $text_label_RED = $left_frame->Label->pack(... ..

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: Basic questions of Tk programming
by GrandFather (Saint) on Jan 23, 2025 at 23:53 UTC

    Can you provide a link to the place you got the code from? Maybe we can get it removed or replaced with something that makes sense?

    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond

        BAH. Either I didn't super search back far enough or SS dropped the ball.

        A pity OP didn't read as far as Annonymonk's reply.

        Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond