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

Dear bretheren, I sincerely try not to bother you with silly stuff, but this one is beyond me... Boss used cut and paste with photoshop to "enhance" the buttons I made for him in my tk script. Now I have a but1.gif and a but2.gif and when a curser comes over this button it should become but2.gif, while normally it's a but1.gif. I'm building this with canvas and getting the ($x, $y) = $mw->pointerxy; coordinates to figure which image I should display. However, I'm unable to make the picture change. Here is the useless code I'm testing out the BUTTON with hover effect on:

#!/usr/bin/perl use warnings; use strict; use Tk::Trace; use Tk; my $mw = MainWindow->new; $mw->fontCreate('medium', -family=>'courier', -weight=>'bold', -size=> +int(-14*14/10)); my $c = $mw->Canvas(-width => 400,-height => 210,-bd => 2,-relief => ' +sunken',-background => 'black',)->pack; $c->createImage(150, 150, -image => $mw->Photo(-file => &update_meter, + -format => 'gif'), -anchor => 'ne', -tags => ['gif']); my $v = 0; $mw->traceVariable(\$v, 'w' => [\&update_meter]); $mw->bind('<Motion>' => sub{ $v += 1 }); my $text = $c->createText( 100,50, -text => $v,-font => 'medium', -fill => 'yellow', -an +chor => 's', -tags => ['text'] ); $c->raise('text'); MainLoop; sub update_meter { my($index, $value) = @_; my ($x, $y) = $mw->pointerxy; my $value_text = "$value x=$x y=$y"; $c->itemconfigure($text,-text => $value_text); my $file; my $file1 = '/home/pasha/perl/tk/but1.gif'; my $file2 = '/home/pasha/perl/tk/but2.gif'; if (($x > 103 && $x < 153) && ($y > 205 && $y < 226)){ #we are + over button $file = $file2; } else { $file = $file1; } }

The buttons are here: http://pashanoid.ru/images/but1.gif and http://pashanoid.ru/images/but2.gif if anyone is interested.

Thank you for your support and help!

Replies are listed 'Best First'.
Re: tk image map like button with hover effect
by zentara (Cardinal) on Jul 04, 2011 at 11:47 UTC
    It's alot simpler than you are trying to make it, but I realize you are trying to work with the tricks you are familiar with. The following code is the way to do this. In Tk ImageMap-color-zones there are more tricks shown, such as base64 encoding the images for more speed. Tk likes all it's images in base64encoded format, and uses it internally, so you can pre-prepare your images base64 encoded, and stuff them into a hash for quicker response.

    There are also tag bindings which you can use on a canvas. Anyways, here is the basic code you need.

    #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = MainWindow->new; my $c = $mw->Canvas(-width => 400,-height => 210,-bd => 2,-relief => ' +sunken',-background => 'black',)->pack; my $image1 = $mw->Photo(-file => './but1.gif', -format => 'gif'); my $image2 = $mw->Photo(-file => './but2.gif', -format => 'gif'); my $but1 = $c->createImage(150, 150, -image => $image1, -anchor => 'ne', -tags => ['but1']); $c->bind( $but1, '<Enter>', sub { $c->itemconfigure( $but1, -image => $image2); }); $c->bind( $but1, '<Leave>', sub { $c->itemconfigure( $but1, -image => $image1); }); MainLoop;
    and for an example of how to use tags to raise or lower images,

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
      I will do like this... but Probably, I'm missing something.
      #!/usr/bin/perl use strict; use warnings; use Tk; my($mw,$img1,$img2,$c,$btn,$id); $mw = MainWindow->new; $c = $mw->Canvas(-width => 400,-height =>200,-background=>'black')->pa +ck; $img1=$c->Photo(-file=>'but1.gif'); $img2=$c->Photo(-file=>'but2.gif'); $btn=$c->Button( -command=>sub{exit;}, -image=>$img1)->pack; $id=$c->createWindow(200,150, -window=>$btn); $btn->bind('<Enter>', => sub{ $btn->configure(-image=>$img2);} ); $btn->bind('<Leave>', => sub{ $btn->configure(-image=>$img1);} ); MainLoop;
        This code is very nice and simple, thank you! However, is there any way to get rid of the border that makes up the button? I like it, but the guy I'm doing this for will certainly not.
      This is great! I figured out how to bind the button to a sub --
      $c->bind( $but1, '<ButtonPress>', sub { #$c->itemconfigure( $but1, -image => $image1); exit; });
        You can also make an "action button" on a Tk canvas. Just make a slightly smaller copy of your active button, and bind ButtonPress and ButtonRelease to switch images, as was shown above. It will simulate a button press. For a pretty fancy way of doing this, using Tk::Zinc instead of the plain canvas, look at the following

        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku ................... flash japh
      This is great! I'm already using base64 encoded images in the program, so the buttons will be an addition. In the first example, how do I make the "button" perform an action, call a sub or something?
Re: tk image map like button with hover effect
by Anonymous Monk on Jul 04, 2011 at 08:47 UTC
    use a Tk::Checkbutton, for example in widget demo see 7. Iconic buttons that use bitmaps.

    Tk::Canvas works the same way

    -bitmap => bitmap -activebitmap => bitmap -disabledbitmap => bitmap ... -image => name -activeimage => name -disabledimage => name