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

Monks, I'm sure there is a simple answer to this but I'm very new to perl and might have seen the answer and not even known it. What I'm trying to do is write a Tk program that displays the contents of a file that contains some meterological data. That part I've gotten down, the problem I'm having is that this file is updated every 5 minutes and I haven't figured out how to refresh the entry widgets. Here is the what I've done so far, any help, comments, or general remarks regarding this will be greatly appreciated.
#!\Perl\bin -w use Tk; $statfile = "c:\\data\\test.txt"; print "BEFORE WHILE\n"; open (FILE, $statfile) || die "Couldn't open file: $!"; my @statarray = <FILE>; foreach (@statarray){chomp;} #####Create Main GUI WINDOW###### my $main = MainWindow->new(); $main->title("FLOWINFO - Port Freeport Real-Time Navigation System"); #####BEGIN MENUBAR CREATION###### my $menu_bar = $main->Frame(-relief => 'groove', -borderwidth => 3)->p +ack(-side=>'top', -fill => 'x'); my $file_mb = $menu_bar->Menubutton(-text => 'File')->pack(-side=>'lef +t'); $file_mb->command(-label => 'Exit', -command => sub{$main->destroy}); my $help_mb = $menu_bar->Menubutton(-text => 'Help')->pack(-side => 'r +ight'); $help_mb->command(-label=>'About', -command =>\&about); $help_mb->command(-label=>'Help', -command =>\&help); ####BEGIN BUILDING GUI BODY######## my $top = $main -> Frame -> pack(-side=>'top', -fill =>'x'); my $left1 = $top -> Frame -> pack(-side =>'left',-pady =>9, -padx => 8 +); ##############MET############################## my $metlabel = $left1 -> Label(-text => ' METEORLOGICAL SENSORS')->pac +k(); $metsensor= $left1->Label(-text =>' Wind Speed ')->pack(); $metsensor= $left1->Label(-text =>' Wind Direction ')->pack(); $metsensor= $left1->Label(-text =>' Air Temperature ')->pack(); $metsensor= $left1->Label(-text =>' Barometric Pressure ')->pack(); $metsensor= $left1->Label(-text =>' Average Gust ')->pack(); my $left2 = $top -> Frame ->pack(-side=>'left',-pady => 2, -padx => 15 +); my $metstatlabel = $left2->Label(-text => 'METEORLOGICAL MEASUREMENTS' +)->pack(); #############ADCP############################## my $right1 = $top -> Frame ->pack(-side=>'right', -pady => 2, -padx=>1 +5); my $adcpstatlabel = $right1->Label(-text => 'ADCP MEASUREMENTS')->pack +(); my $right2 = $top ->Frame ->pack(-side=>'right'); my $adcplabel = $right2->Label(-text => 'ADCP SENSORS')->pack(); $adcpsensor = $right2->Label(-text => 'Drift')->pack(); $adcpsensor = $right2->Label(-text => 'Set')->pack(); $adcpsensor = $right2->Label(-text => 'Water Depth')->pack(); $adcpsensor = $right2->Label(-text => 'Water Temperature')->pack(); close FILE; print "closed File\n"; $main->bind("<Alt-F4>" => sub{exit}); print "Updating Array\n"; $main->repeat( 20000 => \&array_update); MainLoop(); sub array_update { open (FILE, $statfile) || die "Couldn't open file: $!"; my @statarray = <FILE>; close FILE; foreach (@statarray){chomp;} $metstat1->destroy() if Tk::Exists($metstat1); $metstat2->destroy() if Tk::Exists($metstat1); $metstat3->destroy() if Tk::Exists($metstat1); $metstat4->destroy() if Tk::Exists($metstat1); $metstat5->destroy() if Tk::Exists($metstat1); $adcpstat1->destroy() if Tk::Exists(adcpstat1); $adcpstat2->destroy() if Tk::Exists(adcpstat1); $adcpstat3->destroy() if Tk::Exists(adcpstat1); $adcpstat4->destroy() if Tk::Exists(adcpstat1); $metstat1 = $left2->Entry(-width => 5, -textvariable => \$statarray[0] +, -relief => 'sunken')->pack(); $metstat2 = $left2->Entry(-width => 5, -textvariable => \$statarray[1] +, -relief => 'sunken')->pack(); $metstat3 = $left2->Entry(-width => 5, -textvariable => \$statarray[2] +, -relief => 'sunken')->pack(); $metstat4 = $left2->Entry(-width => 5, -textvariable => \$statarray[3] +, -relief => 'sunken')->pack(); $metstat5 = $left2->Entry(-width => 5, -textvariable => \$statarray[4] +, -relief => 'sunken')->pack(); $adcpstat1 = $right1->Entry(-width => 5, -textvariable => \$statarray[ +5], -relief =>'sunken')->pack(); $adcpstat2 = $right1->Entry(-width => 5, -textvariable => \$statarray[ +6], -relief =>'sunken')->pack(); $adcpstat3 = $right1->Entry(-width => 5, -textvariable => \$statarray[ +7], -relief =>'sunken')->pack(); $adcpstat4 = $right1->Entry(-width => 5, -textvariable => \$statarray[ +8], -relief =>'sunken')->pack(); }

Replies are listed 'Best First'.
Re: Problem refreshing TK window after file update
by atcroft (Abbot) on Apr 30, 2004 at 15:47 UTC

    I'm still learning perl/Tk myself, but ran into something similar recently. I wasn't sure which "entry widgets" you were referring to, but could think of two things that may be of help for you. For both, I will refer to this example:

    my $myscale = $mw->Scale( -from => 2, -to => ( $dx - 1 ), -orient => 'horizontal', -label => 'Drawn X:', -variable => \$a_dx )->grid();

    First thing you may wish to look at is that several types of widgets have the property of being able to be associated to a variable reference (such as the -variable option above, or the -textvariable option for Entry widgets), so that (as I understand it) updating the contents of the variable results in an update of the value displayed for them.

    Another thing you may want to look at the configure function for Tk widgets. For instance, say you have a scale object defined as follows: and you update $dx, and want the maximum scale for it to change as well. In that case, you could do the following:

    $myscale->configure( -to => ($dx - 1) );
    which would change the -to configuration item for that scale.

    Hope that helps....

    Update: (2004-04-30) - Reorganized order suggestions were presented, after re-reading and seeing that the original latter seemed potentially more applicable to the OP.

Re: Problem refreshing TK window after file update
by Popcorn Dave (Abbot) on Apr 30, 2004 at 16:06 UTC
    I'm doing something very similar to what you're trying to do in a program I'm working on now. I used the insert and delete methods in Tk::Text to refresh the data I'm pulling down with LWP::Simple.

    I add text using

    $curval->insert('end', "$current\n", "reset");

    and put all new text at the end.

    And to delete

    $curval->delete("1.0", 'end');

    start with the first line, initial character and delete until the end of text.

    Check those methods out and I think they'll do what you're after.

    Hope that helps!

    There is no emoticon for what I'm feeling now.

Re: Problem refreshing TK window after file update
by zentara (Cardinal) on May 01, 2004 at 13:42 UTC
    Without the data you are using it is hard to give you a good answer, because I can't run the code. But.....

    It appears to me you are updating all wrong, and you will probably be creating a "memory-leak" as you run the program. Not a memory-leak in the true sense of debugging c, but you will find your Tk program MAY be consuming more and more memory as it runs for a long period of time.

    The main problem is you are repeatedly destroying and creating widgets to update them. This causes Tk to grow in size.

    What you should do is create the $metstat* and $adcpstat* Entry widgets one time in the main portion of your program, and then in the sub array_update you just update the Entry widgets. Something along these lines:

    sub array_update { open (FILE, $statfile) || die "Couldn't open file: $!"; my @statarray = <FILE>; close FILE; foreach (@statarray){chomp;} $metstat1"->configure(-textvariable => \$statarray[0]); $metstat2"->configure(-textvariable => \$statarray[1]); $metstat3"->configure(-textvariable => \$statarray[2]); $metstat4"->configure(-textvariable => \$statarray[3]); $metstat5"->configure(-textvariable => \$statarray[4]); $adcpstat1"->configure(-textvariable => \$statarray[5]); $adcpstat2"->configure(-textvariable => \$statarray[6]); $adcpstat3"->configure(-textvariable => \$statarray[7]); $adcpstat4"->configure(-textvariable => \$statarray[8]);
    Although you may be able to get away with a simple $main->update since you are using -textvariable in the Entry widgets.

    Also you may have to make the $metstat* $adcpstat* variables global, to access from the sub. (That is the easiest way).


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