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

In my continuing endeveur to create a solitare game in perl (see node PerlSOl (solitare in perl)) I have come across a problem (... er ... another one, anyway).

The question is how does one go about allowing a user to click on a card (a TK::Canvas->createImage type) and drag it about to different places, and then place it down. This presents a plethora of problems (checking if it can go where it is being put, what to do with it if it can't, having some sort of closeenough variable to see if its close enough to pile to count--would canvas -closeenough option be what I want?--etc.).

I think you get the idea. . . now all these things I can play around with and learn from, BUT, in looking for drag/drop procedures in Tk, I found Tk::DragDrop. However, there are 12 module files, all undocumented. I want to know if any one has ever done anything with EITHER this module, or another one that's optionally better, and, if so, can you explain the interface somewhat.

I could go about making my own module to do this, however I'd prefer not to 're-invent the wheel' (and I wouldn't know where to start, and I want to get this done as soon as possible).

Replies are listed 'Best First'.
Re: Dragging/Dropping images with Tk
by stefp (Vicar) on Jul 06, 2002 at 18:57 UTC
    You should look dnd_demo that contains a pod. It is part of the tarball but, like the other demos, is not installed. You should also read the Tk::DropSite doc.

    -- stefp -- check out TeXmacs wiki

      Thanks.

      But, where do I find dnd_demo (not anywhere on my sytem, CPAN, or this site, and a web search would turn up non-domain results--i.e., the game dungeons and dragons, dnd).

      Also, the T::DropSite doc didn't tell me much (aside from the pod commands, the only real 'meat' was:

      use Tk::DropSite qw(...); $widget->DropSite(-entercommand => ..., -dropcommand => ..., -motioncommand => ..., -dropcommand => ..., );
      Which doesn't exactly tell me much on the way of what the things do -- and trying to run a simple call resulted in an error)

      I don't have the latest version of Perl/Tk if that's a probelm (the only way to get it for active state is to have VC++, recommended v.6, if another way I'd be glad to know)

        As I messaged you, you can handle tarballs with winzip. Also, you can search Tk related packages on search.cpan.org. Tk-DKW seems a good complement to raw Tk, specially TK::IconCanvas even if the documentation is... sketchy.

        I am not a windows user so I would not dare to ask you to switch from ActiveState ppm to the cpan installer. This subjet has probably be treated before...

        -- stefp -- check out TeXmacs wiki

        It is years I have not used Tk so I read some docs to refresh my memory. I would indeed implement the "table" with a Tk::Canvas and the cards with bitmaps items. You need to add handlers to move the cards. I will probably send some some code if I can get some juice from my brain cells.

        I first thought using TopLevel windows for moved cards and using Tk::wm overrideredirect to ask the window manager not to decorate the said windows/cards, But this is more complex and does probably work only on X-Window.

        -- stefp -- check out TeXmacs wiki

Re: Dragging/Dropping images with Tk
by dimmesdale (Friar) on Jul 06, 2002 at 21:21 UTC
    Here's a new question, but since it goes along with the same topic I'll keep it here.

    For the deck when the user clicks it I want three cards to be dealt to the waste. However, if there are already three cards there (or two or one conceivably, if a user has played dealt cards), I want to reposition the existing cards to sit 'on top' of each other.

    HOWEVER, I need help in line of a configure method. I see one documented for the Photo type, however that isn't what I need. I don't see anything in line of that for the Image type. Is there a solution short of deleting the image and the making it again with the desired coordinates (and is this as sloppy as it sounds to me?).

      Huh?

      Just keep track of the cards somehow (easiest way is to create an object, cause all you have is photo id's ;D)

      You can re-position photos, so no need to redraw.

      Check out (crazyinsomniac) Re: Tk Canvas Animation, (crazyinsomniac) Re: Win32 Tk JPEG from memory problem, crazy tk xbm tingy, and Tk Rubberband Demo. Hopefully you'll pick up a few tips (at least enough to write what you want, imho of course).

      You might also wanna read the Tk::Canvas pod.

      Here is a ready to run example

      #!/usr/bin/perl -w use strict; use Tk; sub jump_it { my ($c, $thing) = @_; my ($old_x, $old_y) = $c->coords($thing); my $new_pos = $old_x == 10 ? 80 : 10; $c->coords($thing, $new_pos, $new_pos); } =head1 ORIGINAL C<slide_it> function sub slide_it { my ($c, $thing) = @_; for my $i (10..80) { $c->coords($thing, $i, $i); for (my $wait=20000; --$wait;){}; } } =cut sub slide_it # canvas, card { my ($c, $thing) = @_; $$c{__slide_for} = 80; $$c{__slide_count} = 0; $$c{__slide_timer} = $c->repeat(100, # miliseconds [ \&move_thing, $c, $thing, 2, # this many pixels X 2, # this many pixels Y ,] ,); } sub move_thing { my($c, $thing, $nX, $nY) = @_; if( $$c{__slide_count} > $$c{__slide_for} ) { $$c{__slide_timer}->cancel() } $$c{__slide_count}++; $c->move( $thing, #what? $nX, $nY, ,); } my $mw = MainWindow->new; my $c = $mw->Canvas(-relief => 'sunken', -bd => 2, -width => 200, -height => 200); #my $image = $c->Photo(-file => "cards/ah.gif"); my $image = $c->Photo( -data => q{ R0lGODdhJwA5APcAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwMDcwKbK8EAgAGAgAIAgAK +AgAMAg AOAgAABAACBAAEBAAGBAAIBAAKBAAMBAAOBAAABgACBgAEBgAGBgAIBgAKBgAMBgAOBgAA +CAACCA AECAAGCAAICAAKCAAMCAAOCAAACgACCgAECgAGCgAICgAKCgAMCgAOCgAADAACDAAEDAAG +DAAIDA AKDAAMDAAODAAADgACDgAEDgAGDgAIDgAKDgAMDgAODgAAAAQCAAQEAAQGAAQIAAQKAAQM +AAQOAA QAAgQCAgQEAgQGAgQIAgQKAgQMAgQOAgQABAQCBAQEBAQGBAQIBAQKBAQMBAQOBAQABgQC +BgQEBg QGBgQIBgQKBgQMBgQOBgQACAQCCAQECAQGCAQICAQKCAQMCAQOCAQACgQCCgQECgQGCgQI +CgQKCg QMCgQOCgQADAQCDAQEDAQGDAQIDAQKDAQMDAQODAQADgQCDgQEDgQGDgQIDgQKDgQMDgQO +DgQAAA gCAAgEAAgGAAgIAAgKAAgMAAgOAAgAAggCAggEAggGAggIAggKAggMAggOAggABAgCBAgE +BAgGBA gIBAgKBAgMBAgOBAgABggCBggEBggGBggIBggKBggMBggOBggACAgCCAgECAgGCAgICAgK +CAgMCA gOCAgACggCCggECggGCggICggKCggMCggOCggADAgCDAgEDAgGDAgIDAgKDAgMDAgODAgA +DggCDg gEDggGDggIDggKDggMDggODggAAAwCAAwEAAwGAAwIAAwKAAwMAAwOAAwAAgwCAgwEAgwG +AgwIAg wKAgwMAgwOAgwABAwCBAwEBAwGBAwIBAwKBAwMBAwOBAwABgwCBgwEBgwGBgwIBgwKBgwM +BgwOBg wACAwCCAwECAwGCAwICAwKCAwMCAwOCAwACgwCCgwECgwGCgwICgwKCgwMCgwOCgwADAwC +DAwEDA wGDAwIDAwKDAwP/78KCgpICAgP8AAAD/AP//AAAA//8A/wD//////yH5BAAAAAAALAAAAA +AnADkA AAjDAP8JHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypEmKAFICEK +lSpceW MDm2/AczJUaXK2vOvKizJs2VFYHqFOhzYs6YA3P+BCrRJlKaRJ8+PIozadSdEKkKxanVZt +aYXr0u dfnVp9ikWKeCRSjV4VC2ad1qTdi2oVm4ZMs6hVqwqF6yZ/2q/bn06tusULmOrWvX8MzDTR +0v3osS 7eS4TZmaPWsR8FiWnE+KHk26tOnTqFOrLhgQADs=}, -format => 'gif' ); my $card = $c->create('image', 10, 10, -anchor => 'nw', -image => $image); my $j_btn = $mw->Button(-text => 'Jump It', -command => [\&jump_it, $c, $card] ); my $s_btn = $mw->Button(-text => 'Slide It', -command => [\&slide_it, $c, $card] ); $j_btn->pack; $s_btn->pack; $c->pack; MainLoop; __END__
      Here is another one
      #!/usr/bin/perl -w use strict; use Tk; my $MW = MainWindow->new; my $c = $MW->Canvas(-relief => 'sunken', -bd => 2, -width => 200, -height => 200)->pack(); #my $image = $c->Photo(-file => "cards/ah.gif"); my $image = $c->Photo( -data => q{ R0lGODdhJwA5APcAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwMDcwKbK8EAgAGAgAIAgAK +AgAMAg AOAgAABAACBAAEBAAGBAAIBAAKBAAMBAAOBAAABgACBgAEBgAGBgAIBgAKBgAMBgAOBgAA +CAACCA AECAAGCAAICAAKCAAMCAAOCAAACgACCgAECgAGCgAICgAKCgAMCgAOCgAADAACDAAEDAAG +DAAIDA AKDAAMDAAODAAADgACDgAEDgAGDgAIDgAKDgAMDgAODgAAAAQCAAQEAAQGAAQIAAQKAAQM +AAQOAA QAAgQCAgQEAgQGAgQIAgQKAgQMAgQOAgQABAQCBAQEBAQGBAQIBAQKBAQMBAQOBAQABgQC +BgQEBg QGBgQIBgQKBgQMBgQOBgQACAQCCAQECAQGCAQICAQKCAQMCAQOCAQACgQCCgQECgQGCgQI +CgQKCg QMCgQOCgQADAQCDAQEDAQGDAQIDAQKDAQMDAQODAQADgQCDgQEDgQGDgQIDgQKDgQMDgQO +DgQAAA gCAAgEAAgGAAgIAAgKAAgMAAgOAAgAAggCAggEAggGAggIAggKAggMAggOAggABAgCBAgE +BAgGBA gIBAgKBAgMBAgOBAgABggCBggEBggGBggIBggKBggMBggOBggACAgCCAgECAgGCAgICAgK +CAgMCA gOCAgACggCCggECggGCggICggKCggMCggOCggADAgCDAgEDAgGDAgIDAgKDAgMDAgODAgA +DggCDg gEDggGDggIDggKDggMDggODggAAAwCAAwEAAwGAAwIAAwKAAwMAAwOAAwAAgwCAgwEAgwG +AgwIAg wKAgwMAgwOAgwABAwCBAwEBAwGBAwIBAwKBAwMBAwOBAwABgwCBgwEBgwGBgwIBgwKBgwM +BgwOBg wACAwCCAwECAwGCAwICAwKCAwMCAwOCAwACgwCCgwECgwGCgwICgwKCgwMCgwOCgwADAwC +DAwEDA wGDAwIDAwKDAwP/78KCgpICAgP8AAAD/AP//AAAA//8A/wD//////yH5BAAAAAAALAAAAA +AnADkA AAjDAP8JHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypEmKAFICEK +lSpceW MDm2/AczJUaXK2vOvKizJs2VFYHqFOhzYs6YA3P+BCrRJlKaRJ8+PIozadSdEKkKxanVZt +aYXr0u dfnVp9ikWKeCRSjV4VC2ad1qTdi2oVm4ZMs6hVqwqF6yZ/2q/bn06tusULmOrWvX8MzDTR +0v3osS 7eS4TZmaPWsR8FiWnE+KHk26tOnTqFOrLhgQADs=}, -format => 'gif' ); ## CARD my $card = $c->create( 'image', 10, 10, -anchor => 'nw', -image => $image ); $image->bind( 'Tk::Canvas', '<ButtonPress-1>' => [\&DragOn, map{Ev($_)} qw{ x y s } ] ); $image->bind( 'Tk::Canvas', '<ButtonRelease-1>' => [\&DragOff, map{Ev($_)} qw{ x y s } ] ); MainLoop; sub DragOn { my( $C, $X, $Y, $S ) = @_; if( grep { $card eq $_ } $C->find('overlapping', $X, $Y, $X + 1 , $Y + 1 ) ) { $MW->bind( 'Tk::Canvas', '<Motion>' => [\&StickToMouse, map { Ev($_) } qw{ x y s } +] ); } } sub DragOff { my( $C, $X, $Y, $S ) = @_; $MW->bind( 'Tk::Canvas', '<Motion>' => undef, # essentially unbind ); } sub StickToMouse { my( $C, $X, $Y, $S ) = @_; $C->coords( $card, $X, $Y); } __END__