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

I have a Perl/Tk application that is basicallly a gui for displaying an image that is generated by another program. I've set up a socket and I'm using fileevent to read RGB data and put it into a Tk::Photo object. What I would like to have happen: User asks for an image. Window with progress bar pops up. When the image is completely built, progress bar disappears and the image is displayed on the main GUI's Tk::Canvas. My problem appears to be that the program is so busy collecting data off the socket that it doesn't update the gui until later. I've tried putting a progress bar in the canvas, using a second MainWindow for the progress bar, and multiple other configurations. They all have the same problem. If I put a window->update call into the loop that handles the socket messages, I get multiple warnings about deep recursion, and the program slows waaaaay down. Sorry to be so vague. Can anyone help?

Replies are listed 'Best First'.
Re: Progress bar troubles
by kvale (Monsignor) on May 05, 2003 at 20:17 UTC
    Without code, I cannot speak to your recursion problems, but below is code for a progress bar I created for another application. The progress bar is in another window, but could be adapted to you main canvas. Here is the main constructor sub:

    # shows progress of classification sub progress_ui { my($top_root) = @_; $progress_main->destroy if Exists($progress_main); $progress_main = $top_root->Toplevel; my($root) = $progress_main->Frame()->pack( -fill=>'both', -expand=>1 ); $progress_main->title('SpikeSort Progress'); $progress_main->iconname('SpikeSortProgress'); # widget creation my($label_2) = $root->Label ( -text => 'Percentage of trace classified:', ); # this is global $progress_canvas = $root->Canvas ( -height => '0', -highlightthickness => '0', -width => '0', ); my($label_1) = $root->Label ( -textvariable => \$spikes_found, ); # Geometry management $label_2->grid( -in => $root, -column => '1', -row => '1' ); $progress_canvas->grid( -in => $root, -column => '1', -row => '2', -sticky => 'nesw' ); $label_1->grid( -in => $root, -column => '1', -row => '3' ); # Resize behavior management # container $root (rows) $root->gridRowconfigure(1, -weight => 0, -minsize => 30); $root->gridRowconfigure(2, -weight => 0, -minsize => 80); $root->gridRowconfigure(3, -weight => 0, -minsize => 30); # container $root (columns) $root->gridColumnconfigure(1, -weight => 0, -minsize => 420); # additional interface code # draw the thermometer of progress.. $progress_canvas->create( 'line', '25', '40', '395', '40', -width => '40', -fill => 'black', -cap => 'butt', ); }

    The bar is just a thick line and to update the progress bar, just draw a line a little longer each time:

    ... elsif ( $added_text =~ /^sample index: (\d+)/ ) { $progress_width = 25 + 370 * $1 / $total_samples; $progress_canvas->create( 'line', '25', '40', $progress_width, '4 +0', -width => '40', -fill => 'blue', -cap => 'butt', ) if $progress_canvas; } ...

    IIRC, the process of creating the line updates the canvas directly.

    -Mark

      Thanks for your help. It took a couple of different things to get going. I used idletasks instead of update, and that fixed the recursion problem. It also appears that I can't update one MainWindow without updating the other, so I made sure that the main gui didn't receive any changes until the progress bar had finished.