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;
}
| [reply] [d/l] |
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
}
| [reply] [d/l] |
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
| [reply] [d/l] |