Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Tk::ProgressBar and threads

by dannoura (Pilgrim)
on Dec 13, 2005 at 21:18 UTC ( #516432=perlquestion: print w/ replies, xml ) Need Help??
dannoura has asked for the wisdom of the Perl Monks concerning the following question:

hi,

I have a perl script that converts databases and I'd like it to inform the user of its progress. The code below is supposed to increment the progress bar and set it to zero when the "Clear" button is pressed. Unfortunately, it does none of these. What am I doing wrong?

use strict; use Threads; use Tk; use Thread::Queue; use Tk::ProgressBar; my $comm = new Thread::Queue; my ($mw, $percent_done)=create_gui(); threads->new(\&go, $comm, $percent_done)->detach; $mw->repeat( 100, [\&updateScreen, $comm, $percent_done] ); MainLoop(); sub create_gui { my $percent_done=0; my $mw = MainWindow->new( -title => 'Test'); $mw->Label( -text => "percent_done" )->pack; $mw->ProgressBar(-variable => \$percent_done)->pack; $mw->Button ( -text => "Clear", -command => sub {$percent_done=0} )->pack; return ($mw, $percent_done); } sub go { my ($comm, $percent_done)=@_; while(1) { $comm->enqueue( $percent_done+5); select undef, undef, undef, 0.1; } } sub updateScreen { my ($comm, $percent_done)=@_; ($percent_done = $comm->dequeue ) if $comm->pending; }

Comment on Tk::ProgressBar and threads
Download Code
Re: Tk::ProgressBar and threads
by choedebeck (Beadle) on Dec 13, 2005 at 22:34 UTC
    I have never been able to successfully get threads to work using Tk. I was able to get your code working making a few modifications though.
    use strict; use Tk; use Tk::ProgressBar; my ($mw, $percent_done)=create_gui(); $mw->repeat(1000, \&go); MainLoop(); sub create_gui { my $percent_done=0; my $mw = MainWindow->new( -title => 'Test'); $mw->Label( -text => "percent_done" )->pack; $mw->ProgressBar(-variable => \$percent_done)->pack; $mw->Button ( -text => "Clear", -command => sub {$percent_done=0} )->pack; return ($mw, \$percent_done); } sub go { $$percent_done+= 5; }
Re: Tk::ProgressBar and threads
by zentara (Archbishop) on Dec 13, 2005 at 22:36 UTC
    Well it seems like you just put together some code, and "hoped it would work". There are alot of problems in the way you set this up. First, it's "use threads" NOT "use Threads". Second, percent_done needs to be shared if you want to use it across threads in your &go sub. Third, you can't use -textvariable in a progressbar across threads, you need to start a timer, to periodically read $percent_done and update the progressbar. Fourth, you must start all thread code, before any Tk code is invoked.

    If it was me I would start over, this dosn't show any progress, and of course the clear button won't work. So I hacked you code to make it work, but the way you have it set up, it's a 1 shot thread, because you detach it. Notice that if you hit Clear while the thread is running, it will be restored on the next update, because you have no shared control variable in the thread code block, to tell it to stop. See Tk-with-worker-threads for an example of how you can make reusable threads with Tk, without leaking memory on each run.

    #!/usr/bin/perl use warnings; use strict; use threads; use threads::shared; use Tk; use Thread::Queue; use Tk::ProgressBar; my $percent_done; share $percent_done; $percent_done = 0; my $comm = new Thread::Queue; my $progressbar; threads->new(\&go, $comm, $percent_done)->detach; my $mw; ($mw, $percent_done) = create_gui(); $mw->repeat( 100, [\&updateScreen, $comm, $percent_done] ); MainLoop(); sub create_gui { $percent_done=0; my $mw = MainWindow->new( -title => 'Test'); $mw->Label( -text => "percent_done" )->pack; $progressbar = $mw->ProgressBar()->pack; $progressbar->value($percent_done); $mw->Button ( -text => "Clear", -command => sub { $percent_done = 0; $progressbar->value(0); $mw->update; } )->pack; return ($mw, $percent_done); } sub go { my ($comm, $percent_done) = @_; $comm->enqueue( $percent_done + 5); while(1) { $comm->enqueue( $percent_done + 5); select undef, undef, undef, 1; $percent_done += 5; if($percent_done == 100){last} } } sub updateScreen { my ($comm, $percent_d) = @_; $progressbar->value($percent_done); ($percent_done = $comm->dequeue ) if $comm->pending; $progressbar->value($percent_done); }

    I'm not really a human, but I play one on earth. flash japh
Re: Tk::ProgressBar and threads
by Sandy (Deacon) on Dec 13, 2005 at 22:36 UTC

    I'm not sure, but I think you need to update your main window in the sub 'updateScreen'. Updating your window is required if you want to update a progress bar.

    sub updateScreen { my ($comm, $percent_done)=@_; ($percent_done = $comm->dequeue ) if $comm->pending; $mw->update(); # <--- update main window }

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://516432]
Approved by mrborisguy
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (5)
As of 2014-09-18 06:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (108 votes), past polls