Use Tkinter to create GUI development tools (47) Implement the drag and drop function of files and directories in Tkinter.
Python Tkinter is free and open source, so many programmers have developed many new functional modules on it.
tkdnd is a Python wrapper for tk extensions. The tkdnd extension provides an interface to the native platform-specific drag and drop mechanism. Under Unix, the drag-and-drop protocol used is XDND protocol version 5 (also used by the Qt toolkit and KDE and GNOME desktops). Under Windows, use the OLE2 drag and drop interface. Under Macintosh, use Cocoa drag and drop interface.
Once the TkinterDnD2 package is installed, you can safely proceed:
from TkinterDnD2 import *
This will add the TkinterDnD class. Tk and TkinterDnD. TixTk to the global namespace, plus the following constants:
PRIVATE, NONE, ASK, COPY, MOVE, LINK, REFUSE_DROP,
DND_TEXT, DND_FILES, DND_ALL, CF_UNICODETEXT, CF_TEXT, CF_HDROP,
FileGroupDescriptor, FileGroupDescriptor. One of the enabled
classes TkinterDnD.Tk() or (if the tix extension should be used) TkinterDnD.TixTk() is used as the main application window instead of the regular tkinter.Tk() window. This will add drag and drop specific methods to the "Tk" window and all its descendants.
The above is the translation introduced by the original author. Simply put, use root=TkinterDnD.Tk() instead of root=tkinter.Tk() to create the main window of the application, and use tkinter or ttk controls in this application. If you want to use tix, you need to use root=TkinterDnD.TixTk() instead of root=tix.Tk(). If readers do not understand, you can read the Tkinter module in Chapter 8 of my book "Building a Quantitative Investment System with Zero Foundation-Using Python as a Tool". https://item.jd.com/61567375505.html
Chapter 8 Tkinter Module 245
8.1 Use of Tkinter 245
8.2 Properties of Tkinter Control 250
8.3 Tkinter Main Window 260
8.4 Toplevel Sub-Window 263
8.5 Create Window Menu Bar 264
8.6 Create Pop-up Menu 266
8.7 Control Geometry Layout Management Method 269
8.8 Tkinter Common Controls 274
8.9 Tkinter Events and Binding 299
8.10 Ttk Controls 304
8.11 Tix Controls 312
There are two steps to install TkinterDnD2.
1. Download and install tkdnd2.8. The
download URL is as follows:
https://sourceforge.net/projects/tkdnd/files/Windows%20Binaries/ After
downloading and unpacking, copy the folder tkdnd2.8 and place it in Anaconda/tcl/tcl8.6 Or Python3.8/tcl/tcl8.6.
2. Download and install TkinterDnD2
author webpage http://tkinterdnd.sourceforge.net/ After
downloading and unpacking, copy the TkinterDnD2 location as follows:
Anaconda3/Lib/site-packages/TkinterDnD2
or Python3.8 /Lib/site-packages/TkinterDnD2.
After the above two steps are installed, you can use the file drag and drop function in tkinter.
If the original URL is not easy to download, you can also download it from the tkdnd directory of my network disk.
https://pan.baidu.com/s/1jxSaB8JzOu6hNvFipqfGzQ
Below I made a simple demo program, according to the file type dragged and dropped by the user, such as doc or py file, and directory, different icons are displayed.
It is not difficult for readers to use Tkinter to do a file directory display and manager similar to windows based on program examples. The entire source code is given directly below.
# -*- coding: utf-8 -*-
import os
from TkinterDnD2 import *
from tkinter import *
import PIL
#独狼荷蒲qq:2886002
#通通小白python量化群:524949939
#微信公众号:独狼股票分析
root = TkinterDnD.Tk()
root.withdraw()
root.title('TkinterDnD2 拖拽演示')
root.grid_rowconfigure(1, weight=1, minsize=250)
root.grid_columnconfigure(0, weight=1, minsize=300)
Label(root, text='拖拽文件或目录到这里:').grid(
row=0, column=0, padx=10, pady=5)
buttonbox = Frame(root)
buttonbox.grid(row=2, column=0, columnspan=2, pady=5)
Button(buttonbox, text='Quit', command=root.quit).pack(
side=LEFT, padx=5)
file_data = ('R0lGODlhGAAYAKIAANnZ2TMzMwAAAJmZmf///yH5BAEAAAAALAA'
'AAAAYABgAAAPACBi63IqgC4GiyxwogaAbKLrMgSKBoBoousyBogEACIGiyxwoKgGAECI'
'4uiyCExMTOACBosuNpDoAGCI4uiyCIkREOACBosutSDoAgSI4usyCIjQAGCi63Iw0ACE'
'oOLrMgiI0ABgoutyMNAAhKDi6zIIiNAAYKLrcjDQAISg4usyCIjQAGCi63Iw0AIGiiqP'
'LIyhCA4CBosvNSAMQKKo4ujyCIjQAGCi63Iw0AIGiy81IAxCBpMu9GAMAgKPL3QgJADs'
'=')
folder_data = ('R0lGODlhGAAYAKECAAAAAPD/gP///yH+EUNyZWF0ZWQgd2l0aCBHSU1QA'
'CH5BAEKAAIALAAAAAAYABgAAAJClI+pK+DvGINQKhCyztEavGmd5IQmYJXmhi7UC8frH'
'EL0Hdj4rO/n41v1giIgkWU8cpLK4dFJhAalvpj1is16toICADs=')
file_icon = PhotoImage(data=file_data)
#folder_icon = PhotoImage(data=folder_data)
folder_icon= PhotoImage(file="ico/folder.png")
word_icon= PhotoImage(file="ico/word.png")
py_icon= PhotoImage(file="ico/py.png")
canvas = Canvas(root, name='dnd_demo_canvas', bg='white', relief='sunken',
bd=1, highlightthickness=1, takefocus=True, width=600)
canvas.grid(row=1, column=0, padx=5, pady=5, sticky='news')
# store the filename associated with each canvas item in a dictionary
canvas.filenames = {
}
# store the next icon's x and y coordinates in a list
canvas.nextcoords = [50, 20]
# add a boolean flag to the canvas which can be used to disable
# files from the canvas being dropped on the canvas again
canvas.dragging = False
def add_file(filename):
icon = file_icon
file2,type2=os.path.splitext(filename)
if os.path.isdir(filename):
icon = folder_icon
elif type2=='.doc' or type2=='.docx':
icon = word_icon
elif type2=='.py' or type2=='.PY':
icon = py_icon
id1 = canvas.create_image(canvas.nextcoords[0], canvas.nextcoords[1],
image=icon, anchor='n', tags=('file',))
id2 = canvas.create_text(canvas.nextcoords[0], canvas.nextcoords[1] + 30,
text=os.path.basename(filename), anchor='n',
justify='center', width=90)
def select_item(ev):
canvas.select_from(id2, 0)
canvas.select_to(id2, 'end')
canvas.tag_bind(id1, '<ButtonPress-1>', select_item)
canvas.tag_bind(id2, '<ButtonPress-1>', select_item)
canvas.filenames[id1] = filename
canvas.filenames[id2] = filename
if canvas.nextcoords[0] > 450:
canvas.nextcoords = [50, canvas.nextcoords[1] + 80]
else:
canvas.nextcoords = [canvas.nextcoords[0] + 100, canvas.nextcoords[1]]
# drop methods
def drop_enter(event):
event.widget.focus_force()
print('Entering %s' % event.widget)
return event.action
def drop_position(event):
return event.action
def drop_leave(event):
print('Leaving %s' % event.widget)
return event.action
def drop(event):
if canvas.dragging:
# the canvas itself is the drag source
return REFUSE_DROP
if event.data:
files = canvas.tk.splitlist(event.data)
for f in files:
add_file(f)
return event.action
canvas.drop_target_register(DND_FILES)
canvas.dnd_bind('<<DropEnter>>', drop_enter)
canvas.dnd_bind('<<DropPosition>>', drop_position)
canvas.dnd_bind('<<DropLeave>>', drop_leave)
canvas.dnd_bind('<<Drop>>', drop)
# drag methods
def drag_init(event):
data = ()
sel = canvas.select_item()
if sel:
# in a decent application we should check here if the mouse
# actually hit an item, but for now we will stick with this
data = (canvas.filenames[sel],)
canvas.dragging = True
return ((ASK, COPY), (DND_FILES, DND_TEXT), data)
else:
# don't start a dnd-operation when nothing is selected; the
# return "break" here is only cosmetical, return "foobar" would
# probably do the same
return 'break'
def drag_end(event):
# reset the "dragging" flag to enable drops again
canvas.dragging = False
canvas.drag_source_register(1, DND_FILES)
canvas.dnd_bind('<<DragInitCmd>>', drag_init)
canvas.dnd_bind('<<DragEndCmd>>', drag_end)
root.update_idletasks()
root.deiconify()
root.mainloop()
The results of the program are as follows:
Welcome to continue to follow my blog.