Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

multiple activefill

8 views
Skip to first unread message

kdnewton

unread,
Oct 13, 2008, 1:30:48 PM10/13/08
to
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;

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

zentara

unread,
Oct 13, 2008, 4:48:07 PM10/13/08
to
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;

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


Jack D

unread,
Oct 15, 2008, 12:11:15 AM10/15/08
to
"zentara" <zen...@highstream.net> wrote in message
news:6dc7f4hmv15791q3s...@4ax.com...

> 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;

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

kdnewton

unread,
Oct 15, 2008, 11:26:43 AM10/15/08
to
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.

-Kyle

0 new messages