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

I have need for Tk to start performing a given event every N seconds on command. Like so...

my $sub_ref = sub { do...something }; $mw->repeat(1000*60, $sub_ref);

But it goes on forever, which is inconviently long...

So my question is... Once a $foo->repeat() has started, can I stop it afterwards? And if so, how?

Replies are listed 'Best First'.
Re: Interrupting Tk repeat() method
by pg (Canon) on Sep 18, 2005 at 16:38 UTC

    The other way is to use after(). after() will only be triggered once, thus the event handler will only be called once. Inside the event handler, based on the situation, you can decide whether to reschedule itself again. If yes, simply call after() to reschedule itself. For example:

    use Tk; use Tk::MListbox; my $mw = MainWindow->new(); my $count_v = 0; my $stop_v = 0; my $stop = $mw->Checkbutton(-text => "stop", -variable => \$stop_v, -c +ommand => \&schedule)->pack(); my $count = $mw->Label(-text => $count_v)->pack(); $count->after(1000, \&inc); MainLoop; sub inc { $count->configure(-text => $count->cget("-text") + 1); if (!$stop_v) { $count->after(1000, \&inc); } } sub schedule { if (!$stop_v) { $count->after(1000, \&inc); } }
      That is similar to the way gtk-perl does it. In the timer callback, if it returns TRUE, then the timer runs again, if it returns FALSE, the timer stops. It's cleaner, but takes some "readjustment in thinking" after using Tk timers.

      I'm not really a human, but I play one on earth. flash japh
Re: Interrupting Tk repeat() method
by Errto (Vicar) on Sep 18, 2005 at 16:33 UTC
    my $repeater = $mw->repeat(1000*60, $sub_ref);
    ... later ...
    $repeater->cancel;
    This is documented in the Tk::after docs.
Re: Interrupting Tk repeat() method
by zentara (Cardinal) on Sep 19, 2005 at 10:47 UTC
    A trick I often use in timers(when using strict), is declaring them prior to creating them, so you can cancel them from their callback.

    P.S. One of the things I wish the repeat(after) object had was an $timer->is_running method. I always have to set a separate scalar manually to track them.

    use strict; my $stop_flag = 0; my $timer; $timer = $mw->repeat(1000, sub{ #do something #check for stop_flag if( $stop_flag ){ $timer->cancel } });

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