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

后端 未结 4 1091
情话喂你
情话喂你 2020-12-03 16:35

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

相关标签:
4条回答
  • 2020-12-03 16:52

    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')
    
    0 讨论(0)
  • 2020-12-03 17:04

    This is an update from 2020 for MacOS Catalina users.

    Firstly, the tkdnd library project has been moved to github. The latest version is 2.9.3, and if you do not want to compile the library yourself the latest release is 2.9.2.

    Secondly, placing the tkdnd lib on /Library/Tcl doesn't work anymore (you will get "error: tkdnd library not found"). With Catalina, python looks for the tkdnd lib in its own folder, that is /Library/Frameworks/Python.framework/Versions/.../lib. Placing the tkdnd2.9.3 folder in this path works just fine.

    By the way, placing the TkinterDnD2 Python wrapper in /Library/Frameworks/Python.framework/Versions/.../lib/python/site-packages still works on Catalina.

    Just to clarify, I only tested it for Python 3 (3.8.5), I do not know if for Python 2 the solution is the same but I suppose so.

    0 讨论(0)
  • 2020-12-03 17:05

    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.

    0 讨论(0)
  • 2020-12-03 17:09

    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

    0 讨论(0)
提交回复
热议问题