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

Hi there, this is my first post, and first of all... sorry for my english! I have a routine that calls another routine that creates a new Tk object by the repeat method; then, I need to know if the repeat object is working before the caller routine continue with its work; I tried to do this with the select function inside the coller routine; it should wait the change of a variable I set with the callback inside the repeat object; when I do that, it seems that even the callback doesn't start, and the "wait routine" remain in the while/select loop because the variable doesn't change. thak you in advance to everyone for the patience. here some code:
use Tk; my $MW = MainWindow->new(); ... ... $REFRESH{xyz} = \&xyz; ... # The "wait routine" { my ($WidRFR) = $REFRESH{$ID}->(); # Call the function while($CTRL_REFRESH < 1) { select(undef,undef,undef,0.1); } # this + waits until the var changes # Do some stuff } ... # The routine with the repeat Object sub xyz{ my $RFR = $MW->repeat( 500, sub{ { $CTRL_REFRESH = 1; # Do some stuff.... if(...) { $CTRL_REFRESH = 2; } # This is to notify the end o +f the work and it Works } } ); return($RFR); # Pass the object to the caller to make it able to d +estroy it }; ...

Replies are listed 'Best First'.
Re: Perl/Tk repeat method, callback doesn't work if...
by zentara (Cardinal) on May 16, 2011 at 15:02 UTC
    I think I understand your question.

    First, Tk::repeat is a quick shortcut for Tk::after, read "perldoc Tk::after". Look thru Tk::after's methods to see if there is something you can use. Second, you didn't show a complete code example, but with Tk timers, if you declare them BEFORE you create them, you can use their variable name within the callback, like:

    #pseudocode my $timer; # code update line below, I forgot to define $timer $timer = $mw->repeat( 50, { #you can use $timer here if $whatever, $timer->cancel; } ); # declare outside the callback, otherwise a $timer cannot cancel itsel +f

    If you really want to get into a select style usage, within Tk, it dosn't work well, because it will interfere with the eventloop. But there is a workaround. See Tk::Trace in Simple Tk Gauge


    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
      Thank you zentara, about cancel/destroy the repeat object, I do that from the caller routine for a better "logistic" administration (yes, the missing code would show that). I know practically nothing about select function but after some tests I suspected the problems comes from it, so you reinforsed my suspects, I bookmarked your post "Simple Tk Gauge" and I'll study it later. After a first look to the after method, it seems there is nothing usable to solve that problem, I think I'll use the Tk::waitVariable method ( $widget->waitVariable(\$var); ) it should work. I'll post more on this thread if I'll discover more solutions. Thank you again!
        ...a doubt rised about the "waitVariable" method is that I suspect that if the timer of repeat is too small, the repeat could set the variable before the creation of waitVariable object and the program could block:
        sub xyz{ $wid->repeat(1, sub{ $var=1; } ); # after 1 millisecond $var==1 # 1 ms... 2ms... 3ms... } { &xyz; # 6 ms... 7ms... 8ms... $widget->waitVariable(\$var); # will this wait indefinitely because +the var was already changed??? # Continue... never will happen }
        It depends on how repeat works (I don't know); but because it returns before the first pause (see Tk::after documentation) should be possible to do a sufficient reliable use of waitVariables, even if this appears to me like a bad patch...
        Sorry it didn't work for you, but I noticed I didn't quite show the code correctly, neglecting to define $timer, after declaring it as a global. That's maybe why your script dosn't cancel. Also, there is a method DoOneEvent which is very useful to force Tk to update everything before proceeding.

        Here is a little something for you to play with, for waitVariable

        #!/usr/bin/perl use warnings; use strict; use Tk; $|=1; my $count = 0; my $loop = 0; my $mw = new MainWindow(); $mw->Label( -textvariable => \$count )->pack; $mw->Button( -text => 'Start', -command => \&long_job ) ->pack( -side => 'left' ); $mw->Button( -text => 'Stop', -command => sub { $loop = 0; print "$cou +nt\n"; } ) ->pack( -side => 'left' ); MainLoop(); sub long_job { my $var; my $timer = $mw->repeat(100, sub{$var++} ); $loop =1; while($loop){ $loop++; $mw->waitVariable(\$var); $count++; } DoOneEvent(); #must call or will block gui }

        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku ................... flash japh