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

This is surely something stupid... but I have no good ideas tonight. I want to a) create a Tk (main) window, b) after the window has been displayed, call a subroutine, c) when the subroutine has been performed, destroy the window. In my script, Tk is correctly expecting an event to call the subrutine. Which is the best method to automate this?

use strict; use warnings; use Tk; my $mw = MainWindow->new(); $mw->Label( -text => "Wait", -font => [-family => 'times', -size => 20], )->pack(-expand => '1', -fill => 'both'); $mw->MainLoop; doSomething($mw);#this is doing nothing here, it should be automatical +ly called after creation and display of mainwindow sub doSomething{ my $mw = shift; print "Hello!\n"; $mw->destroy; }

Replies are listed 'Best First'.
Re: Calling subrutine after creating Tk mainwindow
by choroba (Cardinal) on Jan 26, 2018 at 16:48 UTC
    By calling MainLoop, the program doesn't continue, it waits for the main window to stop. You can add events to the loop, though: for example, if you want to run something immediately after the creation of the window, you can use after(0,...):
    $mw->after(0, sub { doSomething($mw) });

    Be sure to place this before calling the main loop! It tells the main window to call the given subroutine after 0 miliseconds once the main loop is entered.

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Calling subrutine after creating Tk mainwindow
by tybalt89 (Monsignor) on Jan 26, 2018 at 16:45 UTC
    $mw->after( 1, \&thesubroutine );

    Just before the MainLoop

      Thx

Re: Calling subrutine after creating Tk mainwindow
by kcott (Archbishop) on Jan 27, 2018 at 19:44 UTC

    G'day IB2017,

    Take a look at "Re: Code after MainLoop; Tk", which I wrote about 18 months ago. This is an alternative to what you're currently doing and may be a better option.

    With your posted code, &doSomething and $mw are tightly coupled. You only show &doSomething performing a print which is unrelated to $mw; it seems that $mw is only required for the destroy method.

    Adapting the code I've linked, you could write something far cleaner, which might use this sort of format:

    ... { my $mw = ... ... ... $mw->destroy ... ... MainLoop; } doSomething(); sub doSomething { print "Hello!\n"; }

    "$mw->destroy" could be called explicitly, e.g. via a Button action, or implicitly, e.g. along the lines of the after examples you've already been given. Note that, in the code fragment, $mw only exists in its own, limited, lexical scope; it is completely invisible to any code related to &doSomething.

    It seems odd that you'd want to create a GUI then, as the very first thing, perform some unrelated task which culminates in the destruction of that GUI. If you provide a clearer picture of what you're hoping to accomplish, we can possibly provide better, or at least more focussed, advice.

    — Ken