I'm searching for a way to change the activefill of multiple rectangles based on my cursor position. Imagine hovering the mouse within a grid of rectangles. Is there such a way to "activate" all the rectangles within that column and row, in a crosshair fashion?
Here is some code that might help. I don't know the solution and I've been racking my brain over search engines for a couple nights already.
#!/usr/bin/perl -w
use strict; use Tk;
my ($x, $y); my $iconSize = 20; my ($width, $height) = (3, 3); my ($canvasWidth, $canvasHeight) = ($iconSize+$width*$iconSize, $iconSize+$height*$iconSize);
my $MW = MainWindow->new; my $MF = $MW->Frame->pack; my $c = $MF->Canvas( -width => $canvasWidth, -height => $canvasHeight )->pack;
On Mon, 13 Oct 2008 17:30:48 GMT, kdnewton <1...@2.com> wrote: >I'm searching for a way to change the activefill of multiple rectangles >based on my cursor position. Imagine hovering the mouse within a grid of >rectangles. Is there such a way to "activate" all the rectangles within >that column and row, in a crosshair fashion?
>Here is some code that might help. I don't know the solution and I've >been racking my brain over search engines for a couple nights already.
The secret to using the Canvas is tags. Read the perldoc Tk::Canvas for everything on tags, and search groups.google.com for "Perl Tk canvas tags" for many examples.
It's kind of an art, to see which tag juggling technique to use, but generally you bind to motion or a tag, then find the current item, then addtags or deltags, etc. You can get very clever and make things very efficient. For instance, in the following script, I do it the clunky way, by itemconfiguring a bunch of items returned by find. But you could also define a tag called "lit' (or something), and addtag lit to all rows and cols on enter, then deltags lit on leaving.
#!/usr/bin/perl -w use strict; use Tk;
my ($x, $y); my $iconSize = 20; my ($width, $height) = (10, 10); my ($canvasWidth, $canvasHeight) = ($iconSize+$width*$iconSize, $iconSize+$height*$iconSize);
my $MW = MainWindow->new; my $MF = $MW->Frame->pack; my $c = $MF->Canvas( -width => $canvasWidth, -height => $canvasHeight )->pack;
sub enter { my ($canv) = @_; my $id = $canv->find('withtag', 'current'); my @tags = $canv->gettags($id); #could combine this with step above # my @tags = $canv->gettags( $canv->find('withtag', 'current') ); # print "@tags\n"; # row.20 col.140 current
my ($row) = ( grep /^row\d*/, @tags ); my ($col) = ( grep /^col\d*/, @tags );
> On Mon, 13 Oct 2008 17:30:48 GMT, kdnewton <1...@2.com> wrote:
>>I'm searching for a way to change the activefill of multiple rectangles >>based on my cursor position. Imagine hovering the mouse within a grid of >>rectangles. Is there such a way to "activate" all the rectangles within >>that column and row, in a crosshair fashion?
>>Here is some code that might help. I don't know the solution and I've >>been racking my brain over search engines for a couple nights already.
> The secret to using the Canvas is tags. Read the perldoc Tk::Canvas > for everything on tags, and search groups.google.com for "Perl Tk canvas > tags" for many examples.
> It's kind of an art, to see which tag juggling technique to use, but > generally you bind to motion or a tag, then find the current item, then > addtags or deltags, etc. You can get very clever and make things very > efficient. For instance, in the following script, I do it the clunky > way, by itemconfiguring a bunch of items returned by find. But you > could also define a tag called "lit' (or something), and addtag lit > to all rows and cols on enter, then deltags lit on leaving.
Zentara's code works fine - but I thought I woule point out that there is no need to loop through each item. That is the power of tags. If one tag relates to many items - doing an "itemconfigure" will change all items with that tag (no need to loop).
Here is another solution using Zentara's code (tag methodology):
#!/usr/bin/perl -w
use strict; use Tk;
my ($x, $y); my $iconSize = 20; my ($width, $height) = (10, 10); my ($canvasWidth, $canvasHeight) = ($iconSize+$width*$iconSize, $iconSize+$height*$iconSize);
my $MW = MainWindow->new; my $MF = $MW->Frame->pack; my $c = $MF->Canvas( -width => $canvasWidth, -height => $canvasHeight )->pack;
sub findtag { my ($canv) = @_; my $id = $canv->find('withtag', 'current'); my @tags = $canv->gettags($id); my ($row) = ( grep /^row\d*/, @tags ); my ($col) = ( grep /^col\d*/, @tags ); return ($row,$col);
}
sub enter { my ($canv) = @_; my ($r,$c) = findtag($canv); $canv->itemconfigure($r, -fill=>$canv->itemcget($r,-activefill)); $canv->itemconfigure($c, -fill=>$canv->itemcget($c,-activefill));
}
sub leave{ my ($canv) = @_; $canv->itemconfigure('rect', -fill=>'#AFAFAF'); # note replaced 'all' with 'rect' above - just in case there are other canvas items :-)
}
__END__
I agree with Zentara - the Canvas is great and is a very powerful widget.
Thank you both, Jack D and zentara. Both methods look great. It appears that another of my questions has been answered, as well. I was going to ask how to cause a canvas item to behave as a widget... and bind seems to do just that. Thanks again.