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;
for ($y = $iconSize; $y < $canvasHeight; $y+=$iconSize)
{
for ($x = $iconSize; $x < $canvasWidth; $x+=$iconSize)
{
$c->createRectangle ($x, $y,
$x+$iconSize, $y+$iconSize,
-fill => '#AFAFAF',
-activefill => '#CFCFCF' );
}
}
MainLoop
>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;
for ($y = $iconSize; $y < $canvasHeight; $y+=$iconSize)
{
for ($x = $iconSize; $x < $canvasWidth; $x+=$iconSize)
{
my $rect = $c->createRectangle ($x, $y,
$x+$iconSize, $y+$iconSize,
-fill => '#AFAFAF',
-activefill => '#CFCFCF',
-tags =>['rect',"row.$y", "col.$x"]
);
}
}
$c->bind('rect', '<Enter>', \&enter );
$c->bind("rect", "<Leave>", \&leave );
MainLoop;
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 );
my(@rows) = $canv->find('withtag', $row);
my(@cols) = $canv->find('withtag', $col);
foreach my $r(@rows){
$canv->itemconfigure($r, -fill=>'#CFCFCF')
}
foreach my $c(@cols){
$canv->itemconfigure($c, -fill=>'#CFCFCF')
}
}
sub leave{
my ($canv) = @_;
# print "leave\n";
$canv->itemconfigure('all', -fill=>'#AFAFAF')
}
__END__
Have fun, then Canvas is great,
zentara
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;
for ($y = $iconSize; $y < $canvasHeight; $y+=$iconSize)
{
for ($x = $iconSize; $x < $canvasWidth; $x+=$iconSize)
{
$c->createRectangle ($x, $y,
$x+$iconSize, $y+$iconSize,
-fill => '#AFAFAF',
-activefill => '#CFCFCF',
-tags=>['rect',"row.$y", "col.$x"] );
}
}
$c->bind('rect', '<Enter>', \&enter );
$c->bind("rect", "<Leave>", \&leave );
MainLoop;
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.
Jack
-Kyle