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

hi

if anyone knows of a way to do this please enlighten me. what i have are Gnome2::Canvas objects like ellipeses and rectangles and whatnot. what i would like to do is associate other data with the objects and show that data when events like enter/leave-notify occur.

drawing/showing is no problem, but for the life of me i can not figure out how to identify what object's event has been triggered as they all call the same sub and i could not figure out any way to add some unique attribute to the objects.

i have searched all over for any info but failed turn up anything useful.

i'm probably missing the blindingly obvious but here i go anyway: is there any way of adding any kind of identifying attribute?

thanks,
marksz

  • Comment on unique identifiers for gtk2 canvas objects?

Replies are listed 'Best First'.
Re: unique identifiers for gtk2 canvas objects?
by Tanktalus (Canon) on Feb 09, 2005 at 22:03 UTC

    I've never used gtk2 or anything like that, but this is just screaming out for closures. :-) It'd help people like me help you if you showed the code you had, though. I'm stealing code from Gnome2::Canvas's docs.

    my $box = Gnome2::Canvas::Item->new ($root, 'Gnome2::Canvas::Rect', x1 => 10, y1 => 5, x2 => 150, y2 => 135, fill_color => 'red', outline_color => 'black'); $box->lower_to_bottom; $box->signal_connect (event => sub { my ($item, $event) = @_; warn "event ".$event->type." on $box\n"; });

    The key is to simply use $box, or whatever, in the anonymous subroutine, and it will be forever linked to that instantiation. Even if you create a bunch of different $box's in a loop or in another subroutine, the $box it refers to will always be the correct one.

      isn't ($box==$item) in the example you give? as far as i understand the connected sub gets called with the reference of the object and the event.

      but anyway, i don't see how this would help me. what i whould like to have is something i can use as a key in a hash ref that would hold some related data.

      come to think of it, can't you use objects as hash keys?

        Can't you use the $item as a hash ref? :-)

Re: unique identifiers for gtk2 canvas objects?
by zentara (Cardinal) on Feb 10, 2005 at 13:28 UTC
    i could not figure out any way to add some unique attribute to the objects.

    Use hashes. I do it all the time in Tk(I'm just dabbling in gtk2). You just need to be careful when setting up your keys. Some tips: Don't use your object as a key. For example ( a pseudo code NOT gtk2 syntax ):

    my %rects; my %ovals; for my $num(1..10){ $rects{$num}{'object'} = $canvas->createRect( ...... -tags => [$num , 'rect' ] ); $rects{$num}{'num'} = $num; $rects{$num}{'mydata2'} = "some array or HoA" $rects{$num}{'object'}->bind('Enter',sub{ print "$num\n" }); } for my $num(1..10){ $ovals{$num}{'object'} = $canvas->createOval( ...... -tags => [$num , 'oval' ] ); $ovals{$num}{'num'} = $num; $ovals{$num}{'mydata2'} = "some array or HoA" }
    Once you get the tags from an object, you can do
    my $data = $ovals{$num_from_tags}{'mydata2'}
    You can setup the hashes depending on what you need to do. The above is just a simple example. Just setup your tags to give you and identifier for the "current" selected item. Now you can setup bindings for "current" to get what the tags are for whatever the mouse is in.

    Here is an example from one of the Perl-Gtk2 tutorials. It shows how to add data to a gtk2 object. The idea is similar to what I've described above.(Look for the lines "#Add user data"

    #!/usr/bin/perl ############################################################ # Example of animation on the gnome canvas. # # Dov Grobgeld ############################################################ use Gtk2 '-init'; use Gnome2::Canvas; use strict; my ( $w_top, $w_canvas ); my $min_x = 5; my $max_x = 500; my ( $rect_green, $rect_orange ); ############################################################ # Create the widgets ############################################################ sub create_widgets { $w_top = Gtk2::Window->new; $w_top->signal_connect( destroy => sub { exit } ); my $vbox = Gtk2::VBox->new( 0, 0 ); $w_top->add($vbox); $w_canvas = Gnome2::Canvas->new_aa(); $vbox->pack_start( $w_canvas, 1, 1, 0 ); $w_canvas->set_size_request( 600, 300 ); $w_canvas->set_scroll_region( 0, 0, 600, 300 ); my $quit = Gtk2::Button->new("Quit"); $quit->signal_connect( clicked => sub { exit } ); $vbox->pack_start( $quit, 0, 0, 0 ); $w_top->show_all(); } sub place_objects_on_canvas { my $root = $w_canvas->root(); $rect_green = Gnome2::Canvas::Item->new( $root, "Gnome2::Canvas::Rect", x1 => 240, y1 => 90, x2 => 440, y2 => 180, fill_color_rgba => 0x3cb37180, outline_color => "black", width_units => 2.0 ); # Add user data $rect_green->{dir} = 1; $rect_green->{speed} = 5; $rect_orange = Gnome2::Canvas::Item->new( $root, "Gnome2::Canvas::Ellipse", x1 => 30, y1 => 150, x2 => 250, y2 => 240, fill_color_rgba => 0xb3713c80, outline_color => "black", width_units => 2.0 ); $rect_orange->{dir} = -1; $rect_orange->{speed} = 8; Glib::Timeout->add( 10, \&cb_animation_step ); } ############################################################ # Takes one step of the animation. rect_green is moved by # DELTA_Y_GREEN and rect_orange by DELTA_Y_ORANGE. When they # meet the borders, their direction change ############################################################ sub cb_animation_step { foreach my $r ( $rect_green, $rect_orange ) { # Get old values my ( $old_x1, $old_x2 ) = $r->get( "x1", "x2" ); # Get user data my $dir = $r->{dir} || 1; my $speed = $r->{speed}; # Move the object my $new_x1 = $old_x1 + $dir * $speed; my $new_x2 = $old_x2 + $dir * $speed; # Check if we hit a wall if ( $new_x1 < $min_x || $new_x2 > $max_x ) { $dir = -$dir; $r->{dir} = $dir; $new_x1 = $old_x1 + $dir * $speed; $new_x2 = $old_x2 + $dir * $speed; } # Update new parameter data $r->set( x1 => $new_x1, x2 => $new_x2 ); } # As long as this routine returns TRUE, it will be # called again return 1; } create_widgets(); place_objects_on_canvas(); Gtk2->main();

    I'm not really a human, but I play one on earth. flash japh