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

This may well be the first of a number of questions about using items in a canvas.
I want to build an application that has a canvas on to which different rectangular items are
placed next to each other. The rectangular items will consist of lines and widgets.
The canvas group item (Mastering Perl/Tk page 212) seems to be a good way of creating the rectangular items.
Is this correct?
I want to have a ‘menu’ outside the canvas that allows me to select an item, get the item
on the cursor and place it so that it touches the nearest existing item on the canvas
when I use the mouse button.
Can any monk gives me some clues about how this can be done or perhaps point me
in the direction of an existing Perl example that does something akin to what I want?
  • Comment on Slecting and placing 'groups' on a TK canvas

Replies are listed 'Best First'.
Re: Slecting and placing 'groups' on a TK canvas
by zentara (Cardinal) on May 29, 2008 at 15:02 UTC
    Here is a good start for you Tk Patio/Office layout designer. You will find that collision detection or "snap to grid" will be difficult.

    Here is a start for collision detection, but it may be a dead end.

    #!/usr/bin/perl use warnings; use strict; use Tk; my $dx; my $dy; my $mw = MainWindow->new; $mw->geometry("700x600"); my $canvas = $mw->Canvas(-width => 700, -height => 565, -bg => 'black', -borderwidth => 3, -relief => 'sunken', )->pack; my $closebutton = $mw->Button(-text => 'Exit', -command => sub{Tk::exi +t(0)}) ->pack; my $dr = $canvas->createPolygon(0, 20, 50, 20, 50, 75, 0,75, -fill => 'red', -tags => ['move','red','paver'], ); my $db = $canvas->createPolygon(70, 20, 150,20, 150, 75, 70 , 75, -fill => 'blue', -tags => ['move','blue','paver'], ); my $dg = $canvas->createPolygon(200, 20, 250,20, 250, 75, -fill => 'green', -tags => ['move','green','paver'], ); my $dp = $canvas->createPolygon(300, 20, 350,20, 350, 75, -fill => 'purple', -tags => ['move','purple','paver'], ); $canvas->bind('move', '<1>', sub {&mobileStart();}); $canvas->bind('move', '<B1-Motion>', sub {&mobileMove();}); $canvas->bind('move', '<ButtonRelease-1>', sub {&mobileStop();}); MainLoop; sub mobileStart { my $ev = $canvas->XEvent; ($dx, $dy) = (0 - $ev->x, 0 - $ev->y); $canvas->raise('current'); # print "START MOVE-> $dx $dy\n"; } sub mobileMove { my $ev = $canvas->XEvent; # $canvas->bind('current', '<Leave>', sub {&mobileStop();}); + my @coords_in = $canvas->coords('current'); # print "@coords_in\n"; $canvas->move('current', $ev->x + $dx, $ev->y +$dy); ($dx, $dy) = (0 - $ev->x, 0 - $ev->y); # print "MOVING-> $dx $dy\n"; my @coords = $canvas->coords('current'); #print "@coords\n"; my (@olaps) = $canvas->find('overlapping', $coords[0],$coords[1] +,$coords[4],$coords[5], ); foreach my $id(@olaps){ print $canvas->gettags($id),"\t"; } print "@olaps\n"; print "\n"; if(scalar @olaps > 1){ # Redraw the rect $canvas->coords('current', @coords_in); } } sub mobileStop{ &mobileMove; }

    I'm not really a human, but I play one on earth CandyGram for Mongo
      Many thanks for that, I will see what I can do.
      For the touching test I am hoping that I can analyse
      where the nearest object is and then make the final
      adjustment from the cursor position to the object.
        Someone posted a script not too long ago, that had pretty decent "snap-to-grid" functioning.... sorry I can't find the snippet now. Maybe post another node asking about "tk snap-to-grid".

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