TkDND

What: tkdnd
Where: http://sourceforge.net/projects/tkdnd/ 
       http://www.ellogon.org/petasis/index.php/tcltk-projects/tkdnd 
       https://github.com/petasis/tkdnd  (this branch would not compile, sourceforge listed as recommended source on ellogon.org)
Description: Tk drag and drop interface for Windows (OLE DND), Unix (XDND), and Mac OS X.
       Requires Tk 8.3.3.
       Currently at version 2.8
Binaries:
       Windows: https://sourceforge.net/projects/tkdnd/files/Windows%20Binaries/ 
       Linux: https://sourceforge.net/projects/tkdnd/files/Linux%20Binaries/ 
       OS X: https://sourceforge.net/projects/tkdnd/files/OS%20X%20Binaries/ 
Tutorial: https://wiki.tcl-lang.org/36708 
Updated: 07/2015
Contact: mailing lists.

See Also:

03/2004: Binary rpm packages for Linux available: http://sourceforge.net/project/showfiles.php?group_id=13167&package_id=89951

14/03/2007 I have downloaded tkdnd2.0 and it works; however no instructions are given on installing the files, or which files will be needed for a redistribution of tkdnd. Here are my instructions GWM. I have also had the temerity to remove the text NEW! from the above rpm announcement.

Method (i) place the entire tkdnd2.0 directory in your /tcl/library directory. This is OK for personal use but if you are delivering an application using DND then what files do you need to package up? See:

Method (ii) make a new directory anywhere, but a sensible choice is in the directory where your main program/script resides. Copy the libtkdnd20 (dll,so) the library directory (which contains 4 tcl files) and the pkgIndex.tcl to this directory. Add the new directory to auto_path in your application, call 'package require tkdnd' and use it. Example:

lappend auto_path [file join .. "dont just copy this example directory" tkdnd] ;# where dll/so are
package require tkdnd
pack [label .drop -text "drop files, text here"]  ;# make a drop target
tkdnd::drop_target register .drop *
bind .drop <<Drop>> "tk_messageBox -message \"you dropped %D\"" ;# what to do on drop

NB you can drop files from windows, or highlight some text (eg in this page) and drag it onto the drop target. What you do in response to the drop is your affair. The manual supplied does tell you how to restrict the types of drop, what events can occur and how to create a drag source.


16/10/2009 - Googie: I've just tried to compile alpha6 and during configuration I get:

  checking for Tk private include files... configure: error: Cannot find private header tkInt.h in /home/andreask/dbn/lba/night/builds/linux-x86_64/tk.inst

After making workaround (manually edited configuration script) the unix C implementation misses limits.h header for MAX_LONG, just FYI.

And finally, I couldn't get basic.tcl demo to work, after trying to drag anything I get:

invalid command name "_DoDragDrop"
invalid command name "_DoDragDrop"
  while executing
"_DoDragDrop $source $actions $types $data"
  (procedure "_init_drag" line 10)
  invoked from within
"_init_drag $source $state $X $Y"
  (procedure "tkdnd::_begin_drag" line 21)
  invoked from within
"tkdnd::_begin_drag motion .text_drag_source 272 1849 42"
  (command bound to event)

Also dndSpy.tcl doesn't seem to work - I tried to drop some text from my text editor into it and my mouse cursor was like "drop denied" for all the time and dropping text on any of 2 areas (of the demo window) didn't make any response, at all.

I use Slackware64 13.0 - KDE 4.2, Xorg 1.6.3, Kernel 2.6.29.6.

14/04/2010 - Googie: Any news? I've just downloaded version 2.0 and now it compiles without problems, but I still get error about missing _DoDragDrop command.


To use TkDND from python with tkinter, see https://github.com/drewp/light9/blob/master/light9/tkdnd.py . Sourcing the code is straightforward, but the bind() call took some care. Tkinter's bind() doesn't return the result of your callback, but the DragInitCmd needs to get a certain tcl list back. I addressed this by calling widget._register myself with a callback that returns a python tuple, and then calling bind() with the tcl name of the function I made. It's probably a rarely-used tkinter feature, but if you pass bind() a string name of a tcl function, that function gets called in response to the event.