in reply to Re^2: Drag and Drop in Tkx
in thread Drag and Drop in Tkx

As an update, I still don't know how to use drag and drop in Tkx. Some of the suggestions don't really help. The BWidget example: Drag and Drop Demo, is in TCL not Perl. It is not clear how to convert from TCL to Perl/Tkx, especially in terms of drag and drop. The gentle introduction at Tkx:Tutorial doesn't mention drag and drop. The tutorial at www.tkdocs.com/tutorial does not explain how to do drag and drop and I contacted the tutorial's author and he said:

"I'm not aware of any specific info about drag and drop in Tkx. Because it isn't a standard part of Tk, it's not automatically made a part of Tkx like the built-in Tk things are."

It was suggested that I sent a query to tcltk@perl.org, which I did, but didn't hear anything back. Any additional help would be appreciated.

Replies are listed 'Best First'.
Re^4: Drag and Drop in Tkx
by Anonymous Monk on May 05, 2010 at 21:16 UTC
    I'm assuming you've moved on from this problem, but here's something that might help. Only the core of Tk is accessible by default, but it seems that you can get at the rest of it with a little effort. I spent all day trying to write my own Tkx tooltip functionality, and after failing to successfully debug mysterious memory leaks I stumbled upon a way to use Tk's tooltips.
    Tkx::package_require('tooltip'); Tkx::namespace_import("::tooltip::tooltip"); Tkx::tooltip($widget, "Some text.");
    Note how Tkx::tooltip won't work without the require and import lines. Perhaps you can get at Tk's drag and drop functionality in a similar manner. Good luck.
Re^4: Drag and Drop in Tkx
by Anonymous Monk on Feb 13, 2010 at 04:04 UTC
    the only sure way is to help yourself, funny :)
      Here is rough translation of BWidget example: Drag and Drop Demo, not very difficult, does require learning TCL (easy with tkdocs tutorial), I don't think it will help David
      #!/usr/bin/perl -- use strict; use warnings; use Tkx; Main(@ARGV); exit(0); sub Main { local $Tkx::TRACE = 64; Tkx::package_require('tile'); Tkx::package_require('BWidget'); eval { Tkx::tile__setTheme('xpnative'); 1 } || eval { Tkx::ttk__setTheme('xpnative'); 1 }; drawGUI(); Tkx::MainLoop(); } ## end sub Main sub drawGUI { our @wList; #~ http://wiki.tcl.tk/16126# BWidget example: Drag and Drop Demo #~ wm withdraw . #~ Tkx::wm_withdraw('.'); #~ set t [toplevel .t] #~ wm title $t "BWidgets Demo for Drag 'n Drop enabled buttons." our $t = Tkx::widget->new("."); $t = $t->new_toplevel( -name => ".t" ); $t->g_wm_title("BWidgets Demo for Drag 'n Drop enabled buttons.") ; ## wm title $t "BWidgets Demo for Drag 'n Drop enabled button +s." #~ use DDS; Dump($t); #~ # $Tkx_widget1 = \do { my $v = '.t' }; #~ # bless( $Tkx_widget1, 'Tkx::widget' ); #~ proc wrap {wtype wpath args} { #~ if { [catch {uplevel "#0" package require tile}] == 0 } { #~ return [eval ttk::${wtype} $wpath $args] #~ } else { #~ return [eval $wtype $wpath $args] #~ } #~ } #~ sub wrap { #~ my( $wtype ) = shift; #~ $wtype = "Tkx::new_ttk__$wtype"; #~ return $wtype->(@_); #~ } #~ pack [set f [wrap frame $t.f]] -fill both -expand true #~ pack [set f [ttk::frame $t.f]] -fill both -expand true $t = $t->new_ttk__frame( -name => '.t.f' ); $t->g_pack(qw' -fill both -expand true '); #~ pack [wrap button $f.b1 \ #~ -text "1.) Drag" -image [Bitmap::get new] -compound le +ft \ #~ -command {tk_messageBox -message "Drag"}] -padx 5 -pad +y 5 #~ pack [wrap button $f.b2 \ #~ -text "2.) and" -image [Bitmap::get file] -compound l +eft \ #~ -command {tk_messageBox -message "and"}] -padx 5 -pady + 5 #~ pack [wrap button $f.b3 \ #~ -text "3.) Drop" -image [Bitmap::get copy] -compound l +eft \ #~ -command {tk_messageBox -message "Drop"}] -padx 5 -pad +y 5 #~ pack [wrap button $f.b4 \ #~ -text "4.) Demo" -image [Bitmap::get redo] -compound l +eft \ #~ -command {tk_messageBox -message "Demo"}] -padx 5 -pad +y 5 for my $i ( 1 .. 4 ) { my $m = (qw' 0 Drag and Drop Demo ')[$i]; my $bb = $t->new_ttk__button( -name => "$t.b$i", # auto-name is .b .b2 .b3... -image => Tkx::Bitmap__get( (qw'0 new file copy redo ')[$i] ), -text => "$i.) $m", -command => sub { print "$m\n"; }, ); $bb->g_pack; } ## end for my $i ( 1 .. 4 ) #~ enableDnD [list $f.b1 $f.b2 $f.b3 $f.b4] enableDnD( map { "$t.b$_" } 1 .. 4 ); #~ pack [wrap label $f.lbl -text ""] -padx 5 -pady 5 #~ pack [wrap button $f.b5 -text "Exit Demo." -command {exit 0}] - +padx 5 -pady 5 $t->new_ttk__label( -text => "" )->g_pack(qw' -padx 5 -pady 5 '); $t->new_ttk__button( -text => "Exit Demo", #~ -command => sub { Tkx::destroy('.'); exit; }, -command => [ \&Tkx::destroy, '.' ], )->g_pack(qw' -padx 5 -pady 5 '); #~ Tkx::raise('.'); } ## end sub drawGUI sub enableDnD { for my $w (@_) { # Here we register the widget as a dropsite. #~ Tkx::BWidget__DropSite__register( #~ Tkx::DropSite__register( Tkx::DropSite__register( $w, #~ -dropcmd => \&dropbuttonCmd, -dropcmd => sub { print "dropbuttonCmd\n" }, #~ http://docs.activestate.com/activetcl/8.6/bwidget/DropSite.html #~ -droptypes => { #~ BUTTON_ITEM => {copy => {}, move => {} , link => { +}}, #~ }, ); # Here we register the widget as a dragsite. Tkx::DragSite__register( $w, -dragevent => 1, #~ -draginitcmd => \&dragbuttonCmd, #~ -dragendcmd => \&droppedOntoButtonCmd, -draginitcmd => sub { print "dragbuttonCmd\n"; print "\t $_\n" for @_; print "\t--\n"; }, -dragendcmd => sub { print "droppedOntoButtonCmd\n"; print "\t $_\n" for @_; print "\t--\n"; }, ); # Here we have to bind the data type BUTTON_ITEM to the mouse. #~ Tkx::DragSite__include(qw' Widget BUTTON_ITEM <B1-Motion> '); } ## end for my $w (@_) } ## end sub enableDnD

        Thanks. That helped a little. But, the code you have doesn't seem to do anything about the drop site. The Tkx::DropSite_Register() call has a -dropcmd that simply prints "dropbuttonCmd", but that is never printed. I tried creating an entry widget and registering it as a drop site and was not able to get the -dropcmd or -dropovercmd commands to fire.

        So, I'm still unable to do what I would like to do: drag a file from windows explorer onto a widget and have the widget know the name of the file that was dropped.

        I took the code you had and modified it. I took out the comments that were from the original TCL BWidget code (for simplicity) and I specified subs for the various drag/drop commands. Also took out the extraneous topwindow. Also, when the -draginitcmd sub is called it must return 3 things (type of data, list of operations, and the data), so I added a return to my sub. The data part is then successfully passed to the -dragendcmd sub, but I'm not clear as far as what should be specified for the type and list of operations.

        Seems close, but still doesn't work.

        Dave

        My version that does 'drag' but not 'drop':

        #!/usr/bin/perl -- use strict; use warnings; use Tkx; my $text = "abc"; Main(@ARGV); exit(0); sub Main { local $Tkx::TRACE = 64; Tkx::package_require('tile'); Tkx::package_require('BWidget'); eval { Tkx::tile__setTheme('xpnative'); 1 } || eval { Tkx::ttk__setTheme('xpnative'); 1 }; drawGUI(); Tkx::MainLoop(); } sub drawGUI { our $t = Tkx::widget->new("."); $t->g_wm_title("BWidgets Demo for Drag 'n Drop enabled buttons."); $t = $t->new_ttk__frame( -name => '.f' ); $t->g_pack(qw '-fill both -expand true'); for my $i ( 1 .. 4 ) { my $m = (qw' 0 Drag and Drop Demo ')[$i]; my $bb = $t->new_ttk__button(-name => "$t.b$i", # auto-name + is .b .b2 .b3... -image => Tkx::Bitmap__get( (qw'0 + new file copy redo ')[$i] ), -text => "$i.) $m", -command => sub { print "$m\n"; } +); $bb->g_pack; } enableDnD( map { "$t.b$_" } 1 .. 4 ); $t->new_ttk__button(-text => "Exit Demo", -command => [ \&Tkx::destroy, '.' ])->g_pack(q +w '-padx 5 -pady 5'); my $entry = $t->new_ttk__entry(-width => 20, -textvariable => \$te +xt); Tkx::DropSite__register($entry, -dropcmd => \&dropcmdEntry, -dropovercmd => \&dropovercmdEntry, -droptypes => {"text", {"copy", "none"}}); $entry->g_pack(qw '-padx 5 -pady 5'); } sub enableDnD { for my $w (@_) { Tkx::DropSite__register($w, -dropcmd => \&dropButtonCmd); Tkx::DragSite__register($w, -dragevent => 1, -draginitcmd => \&dragInitCmd, -dragendcmd => \&dragEndCmd); } } sub dropButtonCmd { my @args = (@_); print "in dropButtonCmd\n"; for (my $i = 0; $i < scalar @args; $i++) { print "arg $i = '$args[$i]'\n" if defined $args[$i]; } return "abc"; } sub dragInitCmd { my @args = (@_); print "in dragInitCmd\n"; for (my $i = 0; $i < scalar @args; $i++) { print "arg $i = '$args[$i]'\n" if defined $args[$i]; } my $data = "\"Button " . $args[3] . "\""; return ("text", ("copy"), $data); } sub dragEndCmd { my @args = (@_); print "in dragEndCmd\n"; for (my $i = 0; $i < scalar @args; $i++) { print "arg $i = '$args[$i]'\n" if defined $args[$i]; } } sub dropcmdEntry { print "dropcmdEntry\n"; return "entry"; } sub dropovercmdEntry { print "dropovercmdEntry\n"; }