Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: perl gtk2 thumbnail viewer with threads

by zentara (Archbishop)
on Nov 15, 2008 at 14:23 UTC ( [id://723797]=note: print w/replies, xml ) Need Help??


in reply to perl gtk2 thumbnail viewer with threads

It's pretty hard to say what your exact problem is without seeing a minimal working code example, but using the ESP module, I think what you are looking for is a single usuable thread, that processes the images(looping thru them), then use an Idle->add in the thread after each thumbnail is created, to add it to the widget in the main Gtk2 thread.

Here is the basic idea of using Idle->add, it is the preferred way for threads to manipulate widgets in the main thread. The 2 second wait, you mention, hints at the eventloop being lazy in updating everything. The Idle->add will instruct the eventloop to add the new thumbnail to the display widget, at the first possible opening in event processing.

Glib::Idle->add is the great advance that Gtk2 made over Tk, to allow threads to access the gui widgets safely. And DO NOT spawn a new thread to process each image, that will be very slow. Reuse a single (or maybe a couple) of threads.

#!/usr/bin/perl use warnings; use strict; use threads; use threads::shared; use Glib qw/TRUE FALSE/; use Gtk2 qw/-init -threads-init/; Glib::Object->set_threadsafe (TRUE); #setup shared hash my %shash; share(%shash); #will work for first level keys $shash{'go'} = 0; $shash{'work'} = ''; $shash{'die'} = 0; my $num:shared = 0; my $window = Gtk2::Window->new('toplevel'); $window ->signal_connect( 'destroy' => \&delete_event ); $window->set_border_width(10); $window->set_size_request(300,300); my $vbox = Gtk2::VBox->new( FALSE, 6 ); $window->add($vbox); $vbox->set_border_width(2); my $hbox= Gtk2::HBox->new( FALSE, 6 ); my $hbox1 = Gtk2::HBox->new( FALSE, 6 ); $vbox->pack_end($hbox,FALSE,FALSE,0); $vbox->pack_end (Gtk2::HSeparator->new, FALSE, FALSE, 0); $vbox->pack_end($hbox1,FALSE,FALSE,0); $hbox->set_border_width(2); $vbox->pack_end (Gtk2::HSeparator->new, FALSE, FALSE, 0); my $ebutton = Gtk2::Button->new_from_stock('gtk-quit'); $hbox->pack_end( $ebutton, FALSE, FALSE, 0 ); $ebutton->signal_connect( clicked => \&delete_event ); my $pbar = Gtk2::ProgressBar->new(); $pbar->set_pulse_step(.1); $hbox->pack_start($pbar,1,1,0); my $label_w_markup = Gtk2::Label->new(); $label_w_markup->set_markup("<span foreground=\"yellow1\" size=\"40000\">$num</span>"); $vbox->pack_end($label_w_markup,FALSE,FALSE,4); ###################################################### my $tbutton = Gtk2::Button->new_with_label('Run Thread'); $hbox1->pack_start($tbutton , 1, 1, 0 ); my $lconnect = $tbutton->signal_connect( clicked => sub{ launch() }); my $sconnect; $window->show_all(); $pbar->hide; #needs to be called after show_all #create 1 sleeping thread passing it the label and pbar to control my $thread = threads->new(\&work, $label_w_markup, $pbar); Gtk2->main; ###################################### sub delete_event { $shash{'go'} = 0; $shash{'die'} = 1; $thread->join; Gtk2->main_quit; return FALSE; } ####################################### sub launch{ $pbar->show; $tbutton->set_label('Stop Thread'); $tbutton->signal_handler_block($lconnect); $sconnect = $tbutton->signal_connect( clicked => sub{ stop() }); $shash{'go'} = 1; } ################################################## sub stop{ print "stopped\n"; $shash{'go'} = 0; $pbar->hide; $tbutton->set_label('Run Thread'); $tbutton->signal_handler_block ($sconnect); $tbutton->signal_handler_unblock ($lconnect); } ######################################################### sub work{ my ($label,$pbar) = @_; $|++; while(1){ if($shash{'die'} == 1){ return }; if ( $shash{'go'} == 1 ){ $num = 0; while(1){ $num++; if($num > 30){last} Glib::Idle->add( sub{ if($shash{'die'} == 1){ return }; $label->set_markup("<span foreground=\"yellow1\" size=\"40000\">$num</span>"); $pbar->pulse; return FALSE; }); select(undef,undef,undef, .1); if($shash{'go'} == 0){last} if($shash{'die'} == 1){ return }; } #if reach this point, the thread has finished print "my results = $num\n"; Glib::Idle->add( sub{ if($shash{'die'} == 1){ return }; $label->set_markup("<span foreground=\"green\" size=\"60000\">$num</span>"); $pbar->hide; return FALSE; }); $shash{'go'} = 0; #turn off self before returning }else { select(undef,undef,undef,.1) } #sleep time } }

I'm not really a human, but I play one on earth Remember How Lucky You Are

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://723797]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (3)
As of 2024-04-24 19:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found