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

I want to use the group function with a Perl canvas.
Mastering Perl/Tk, page 212 shows how to add two members to the group
that is –members => [$one, $two] where $one and $two are the names of widgets to form the group.
I want to be able to add variable numbers of widgets.
The widget names can be stored in arrays or possibly hashes.
How would I alter the –members ‘part’ so that I can do this?

Replies are listed 'Best First'.
Re: Canvas group members syntax
by zentara (Cardinal) on Jun 03, 2008 at 11:49 UTC
    I like the concept of groups, but it is poorly documented in Tk (as opposed to Tk::Zinc where it is widely used). In Tk, it is probably easier to stick with the simpler tags mechanism. Then when you create items, you specify the -tags=>'one','two','etc'

    Later, when you want to add or remove a tag from a item(s) , you use addtag or dtag to remove tags from a list of items. It is also useful to use "find" to find all items with a certain tag, then loop thru those items to remove a tag(s). The following is actually a simple example, where you addtag for a lasso, then remove the tags with a right click. Left-drag to make lasso, right click drag on an highlighted rect to move all selected, finally a right-click release clears the tag.


    I'm not really a human, but I play one on earth CandyGram for Mongo
      Many thanks for that.
      I have tried to use tags as you suggest by adding the same tag to a number of items
      that I was going to use as a group.
      I then set the following binds where $last_tag_global contained the tag I set on the items.
      $wg{Layout_Canvas}->bind($last_tag_global, '<1>', sub {&mobileStart(); +}); $wg{Layout_Canvas}->bind($last_tag_global, '<B1-Motion>', sub {&mobile +Move();}); $wg{Layout_Canvas}->bind($last_tag_global, '<ButtonRelease-1>', sub {& +mobileStop();});
      I then used the following subroutines (which I found on another Monks thread) to select the items that had the tag, ‘jump’
      them onto the cursor and move them to the required position.
      sub mobileStart { my $ev = $wg{Layout_Canvas}->XEvent; ($dx_cursor, $dy_cursor) = (0 - $ev->x, 0 - $ev->y); $wg{Layout_Canvas}->raise('current'); print "START MOVE-> $dx_cursor $dy_cursor\n"; } sub mobileMove { my $ev = $wg{Layout_Canvas}->XEvent; $wg{Layout_Canvas}->move('current', $ev->x + $dx_cursor, $ev->y ++$dy_cursor); ($dx_cursor, $dy_cursor) = (0 - $ev->x, 0 - $ev->y); print "MOVING-> $dx_cursor $dy_cursor\n"; } sub mobileStop{&mobileMove;}
      This nearly worked except that it would only move one of the items at a time and only
      when the cursor was exactly or nearly exactly over a section (for example a side of a rectangle drawn with canvasRectangle) of the item.
      What do I have to do so that I can select all of the items that have a particular tag
      (by placing the cursor somewhere in the 'middle' of the items that have the tag)
      and move them together to where I want them to be?
        I think that I may have solved this problem. I replaced ‘current’ in the mobileStart and
        mobileMove subroutines with the name of the tag ($last_tag_global)
        attached to the items I wanted to move
        and all works as I want (so far!).
        (Also, I think that the subroutines I included in my last
        did come from the original 'replier').
        What do I have to do so that I can select all of the items that have a particular tag (by placing the cursor somewhere in the 'middle' of the items that have the tag) and move them together to where I want them to be?

        You can use the lasso which I showed earlier at Re: Canvas group members syntax or use the "find" method with the "closest" option to find the closest item to that mouse point. addtag also employs closest(where it is explained).

        You will find that it is an "art" to come up with a clever sub, to do what you want with tags. I often will suddenly realize a week later, that there is a more simple/clever way, than what I start out with. It usually involves using find( with some criteria), then looping thru all the items found, checking their tags, then adding or deleting tags to items, etc. For instance, you could have a bunch of colored geometric shapes( squares, circles,rects,etc), each colored differently. If they were tagged properly, you could click the mouse somewhere, find all 'red' ones within a certain distance, then filter out only the red circles.... then do something with them only. Be creative! Think ahead about systems where you dynamically add and remove tags constantly....you will have full control then.


        I'm not really a human, but I play one on earth CandyGram for Mongo
Re: Canvas group members syntax
by zentara (Cardinal) on Jun 03, 2008 at 12:59 UTC
    If you really want to use the group syntax, this is how you would do it. You just treat the group as any other canvas item and configure it. But this can all be done easier with tags, IMHO, but use what makes sense to you. This code is not perfect, it dosn't handle errors correctly, like trying to Change Group twice.....it aborts..... with tags it would be no problem.....you can have duplicate tags.

    I'm not really a human, but I play one on earth CandyGram for Mongo