How to Install and Use TkDnD with Python Tkinter on OSX?

I've spent some time to search for workable solution to do Drag and Drop behavior with Python Tkinter on OSX platform, and the most possible solution found is TkDnD library. http://sourceforge.net/projects/tkdnd/files/

However I cannot find any manual or guide about the installation and basically no sample on OSX. Can anyone share their experience with me?

Furthermore, is it not a good choice to use Tkinter as a GUI solution? My users are all OSX platform and Python is preinstalled on all these machines. Any good suggestion to find a native GUI support without additional installation? PyQT seems to be another choice, but not sure if it requires the additional installation on Client machine.


Solution 1:

I got this working on both Windows (10) and OSX (10.11) by downloading:
A) Tk extensions tkdnd2.8 from https://sourceforge.net/projects/tkdnd/
B) Python wrapper TkinterDnD2 from https://sourceforge.net/projects/tkinterdnd/

On OSX:
1) Copy the tkdnd2.8 directory to /Library/Tcl
2) Copy the TkinterDnD2 directory to /Library/Frameworks/Python.framework/Versions/.../lib/python/site-packages
(Use the sudo command for copying files on OSX due to permissions.)

On Windows:
1) Copy the tkdnd2.8 directory to ...\Python\tcl
2) Copy the TkinterDnD2 directory to ...\Python\Lib\site-packages

And here's a simple test case based on python drag and drop explorer files to tkinter entry widget. The TkinterDnD2 download comes with much more robust examples.

    import sys
    if sys.version_info[0] == 2:
        from Tkinter import *
    else:
        from tkinter import *
    from TkinterDnD2 import *

    def drop(event):
        entry_sv.set(event.data)

    root = TkinterDnD.Tk()
    entry_sv = StringVar()
    entry_sv.set('Drop Here...')
    entry = Entry(root, textvar=entry_sv, width=80)
    entry.pack(fill=X, padx=10, pady=10)
    entry.drop_target_register(DND_FILES)
    entry.dnd_bind('<<Drop>>', drop)
    root.mainloop()

Update: the above procedure works for Python 2 or 3.

Solution 2:

This is an update from 2017, with a bit more detail, since Mac decided to make it impossible to write files to /System/Library. The following solution is also cross-platform, since I am currently writing an app for both Windows/Mac that uses TkDnD.

The following solution works with pyInstaller, and also with Mac OS 10.12 and Windows 7.

First, we need to get a path to where tkDnD is. By default, I place tkdnd2.8 folder next to main.py.

import sys, os
if getattr(sys, 'frozen', False):
    # If the application is run as a bundle, the pyInstaller bootloader
    # extends the sys module by a flag frozen=True and sets the app 
    # path into variable _MEIPASS'.
    application_path = sys._MEIPASS
else:
    application_path = os.path.dirname(os.path.abspath(__file__))

TK_DND_PATH = os.path.join(application_path,'tkdnd2.8')

Note that Ellis's solution works Tcl directly, modifying the path. Make sure that SOMEWHERE, you have something along this gist:

import tkinter as tk
root = tk.Tk()
root.eval('lappend auto_path {' + TK_DND_PATH + '}')

After this, whenever you happen to actually import tkDnD, it will find it. I used DnD.py. Without the 'lappend auto_path' command, my program could never find tkDnD.

https://mail.python.org/pipermail/tkinter-discuss/2005-July/000476.html

Solution 3:

I spent a few days to figured out how to install TkDnD lib, although it sounds like an easy question but did confused me a little while.

Two ways to install TkDnD on OSX: A. Copy to /System/Library/Tcl/8.x: OSX preinstalled Python already, and this is the path where Tcl library is installed. TkDnd lib will be loaded automatically while using Tk/Tcl lib.

B. Set os.environ['TKDND_LIBRARY'] to the location of TkDnd2.x.dylib: Sample code:

if sys.platform == 'win32':
   if getattr(sys, 'frozen', False):
      os.environ['TKDND_LIBRARY'] = os.path.join(os.path.dirname(sys.executable), 'tkdnd2.7')