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

Hi,

I am creating a screen capture gui using perl/TK. The script will capture a screen using imageMagick. I then display the captured image in my main window. I would like to delete the image and remove it from the display. I tried using destroy(), however I get the following error when I attempt to delete:

Tk::Error: Can't call method "destroy" without a package or object re +ference at ./Capture4.pl line 80. Tk callback for .frame.pane.frame.frame.button Tk::__ANON__ at /usr/lib/perl5/Tk.pm line 250 Tk::Button::butUp at /usr/lib/perl5/Tk/Button.pm line 175 <ButtonRelease-1> (command bound to event)

I would like the window to redraw without the image. Perhaps there is a better way to do this? Any help would be appreciated. Oh! here is the code to the script

#!/usr/bin/perl -w use strict; use Tk; use Tk::WinPhoto; use Tk::JPEG; use Tk::Pane; my $mw = MainWindow->new(); $mw->minsize(qw(670 510)); $mw->configure(-background=>'gray'); $mw->title("Screen Capture GUI"); my $img_count = 0; my $but_capture = $mw->Button( -text => "Capture Screen", -command => +sub { \&Grab() } ); $but_capture -> place(-x=>10,-y=>5, -width=>650); my $exit = $mw->Button( -text => "Exit", -command => sub { exit } ); $exit -> place(-x=>560,-y=>460, -width=>100); my $frame2_1 = $mw->Scrolled(qw/Pane -scrollbars ose/); $frame2_1 -> place(-x=>10,-y=>50, -width=>650, -height=>400 ); MainLoop(); sub Grab(){ ###################################################################### +#### #Creating file handle and taking picture my $tim = time(); my $fname = "/tmp/".$tim.".jpg"; print "$fname\n"; system("import -frame $fname"); #resize to display in window my $fname2=$fname."sm.jpg"; system("convert -size 350X350 $fname -resize 350x350 $fname2"); ###################################################################### +#### $img_count++; my $mini; #Frame packed in scrolling Pane $mini = $frame2_1->Frame(-background=>'#3300ff')->pack(-anchor => 'w', + -fill =>"x"); #create new frame to hold new image contents my $img_label = $mini->Label(-text=>"Image $img_count"); $img_label ->pack(); my $pic_location = $mini->Label(-text=>"Pathname:"); $pic_location ->pack(); my $pic_fname = $mini->Entry(-width=>50,-textvariable=>"$fname"); $pic_fname ->pack(); my $pic = $mini->Photo( -file =>"$fname2"); my $f =$mini->Label(-image => $pic); $f ->pack(); my $but_delete = $mini ->Button( -text => "Delete Image", -command => +sub { \&Delete($mini) } ); $but_delete -> pack(); my $blank1 = $frame2_1->Label(-text=>""); $blank1 ->pack(); } sub Delete(){ my $fn =@_; $fn ->destroy; }

Replies are listed 'Best First'.
Re: Issue destroying image using perl/TK
by lamprecht (Friar) on Mar 22, 2011 at 22:22 UTC
    my $fn =@_;

    does not do what you think it does


    Cheers, Christoph

      Specifically,
          my $fn = @_;
      initializes  $fn with the number of elements in the  @_ array (array evaluated in scalar context). What is almost certainly wanted is
          my ($fn) = @_;
      or better yet
          my $fn = shift;
      to initialize  $fn with the first element (index 0) of the array, Update: which, in this case, is an object reference by which an object method is called.

        This did the trick. Thanks

        @_ is the list of incoming parameters to a subroutine. What is the significants of () around the scaler pv?

Re: Issue destroying image using perl/TK
by Khen1950fx (Canon) on Mar 23, 2011 at 10:25 UTC
    Your screen capture doesn't work. Based on this, here's a sub that does a full capture.
    #!/usr/bin/perl use strict; use warnings; use Tk; use Tk::WinPhoto; my $mw = MainWindow->new(); full_capture(); MainLoop; sub full_capture { my @id = grep { $_ =~ 'Window id' } split( "\n", `xwininfo -root` +); my @ids = split( ' ', $id[0] ); ( my $id ) = grep { $_ =~ /0x/ } @ids; my $image = $mw->Photo( -format => 'Window', -data => oct( $mw->id ), -data => oct('0x00022'), -data => oct($id) ); my $pathname = './rootwindow.' . time . '.png'; $image->write( $pathname, -format => 'BMP | PPM | XPM' ); }
      I have seen code similar to this, however it does not do everything I needed.

      I am using imagemagick to perform the screen grab. It has features for grabbing the window under the cursor and rubber-banding regions with the mouse. I particularly like the -frame option that allows the image to capture the window manager frame. Being a separate application, it must be installed on the linux platform for it to work. It can be downloaded from:

      http://www.imagemagick.org/script/index.php

      PS. The command line invocation for imagemagick is a bit misleading. The command to make a screen grab is

      import -frame some_pic_name.jpg
      Cheers, Tim