Drag and drop multiple files (Windows)

Post here if you need help with creating a Graphical User Interface in Python.

Drag and drop multiple files (Windows)

Postby mitma » Mon Oct 21, 2013 2:13 am

I'm new in python and I'm experimenting myself in a script to automatize a conversion command from a .obj to a .js file with a GUI which uses Tkinter.
I would improve it with a drag and drop function to upload files as input for conversion command, but occur some problems; this is the script:

a) there is a tkdnd_wrapper.py which contains this code (taken from here):

Code: Select all
import os
import Tkinter

def _load_tkdnd(master):
    tkdndlib = os.environ.get('TKDND_LIBRARY')
    if tkdndlib:
        master.tk.eval('global auto_path; lappend auto_path {%s}' % tkdndlib)
    master.tk.eval('package require tkdnd')
    master._tkdnd_loaded = True

class TkDND(object):
    def __init__(self, master):
        if not getattr(master, '_tkdnd_loaded', False):
        self.master = master
        self.tk = master.tk

    # Available pre-defined values for the 'dndtype' parameter:
    #   text/plain
    #   text/plain;charset=UTF-8
    #   text/uri-list

    def bindtarget(self, window, callback, dndtype, event='<Drop>', priority=50):
        cmd = self._prepare_tkdnd_func(callback)
        return self.tk.call('dnd', 'bindtarget', window, dndtype, event,
                cmd, priority)

    def bindtarget_query(self, window, dndtype=None, event='<Drop>'):
        return self.tk.call('dnd', 'bindtarget', window, dndtype, event)

    def cleartarget(self, window):
        self.tk.call('dnd', 'cleartarget', window)

    def bindsource(self, window, callback, dndtype, priority=50):
        cmd = self._prepare_tkdnd_func(callback)
        self.tk.call('dnd', 'bindsource', window, dndtype, cmd, priority)

    def bindsource_query(self, window, dndtype=None):
        return self.tk.call('dnd', 'bindsource', window, dndtype)

    def clearsource(self, window):
        self.tk.call('dnd', 'clearsource', window)

    def drag(self, window, actions=None, descriptions=None,
            cursorwin=None, callback=None):
        cmd = None
        if cursorwin is not None:
            if callback is not None:
                cmd = self._prepare_tkdnd_func(callback)
        self.tk.call('dnd', 'drag', window, actions, descriptions,
                cursorwin, cmd)

    _subst_format = ('%A', '%a', '%b', '%D', '%d', '%m', '%T',
            '%W', '%X', '%Y', '%x', '%y')
    _subst_format_str = " ".join(_subst_format)

    def _prepare_tkdnd_func(self, callback):
        funcid = self.master.register(callback, self._dndsubstitute)
        cmd = ('%s %s' % (funcid, self._subst_format_str))
        return cmd

    def _dndsubstitute(self, *args):
        if len(args) != len(self._subst_format):
            return args

        def try_int(x):
            x = str(x)
                return int(x)
            except ValueError:
                return x

        A, a, b, D, d, m, T, W, X, Y, x, y = args

        event = Tkinter.Event()
        event.action = A       # Current action of the drag and drop operation.
        event.action_list = a  # Action list supported by the drag source.
        event.mouse_button = b # Mouse button pressed during the drag and drop.
        event.data = D         # The data that has been dropped.
        event.descr = d        # The list of descriptions.
        event.modifier = m     # The list of modifier keyboard keys pressed.
        event.dndtype = T
        event.widget = self.master.nametowidget(W)
        event.x_root = X       # Mouse pointer x coord, relative to the root win.
        event.y_root = Y
        event.x = x            # Mouse pointer x coord, relative to the widget.
        event.y = y

        event.action_list = str(event.action_list).split()
        for name in ('mouse_button', 'x', 'y', 'x_root', 'y_root'):
            setattr(event, name, try_int(getattr(event, name)))

        return (event, )

b) then, there is a second script with this code:

Code: Select all
import sys
import os
# os.environ['TKDND_LIBRARY'] = DIRECTORYTOTHETKDNDBINARY # I inactivated this because I installed the tkdnd library inside Python
import Tkinter
from tkdnd_wrapper import TkDND
import shlex, subprocess
from subprocess import Popen, PIPE
import glob
import shutil

root = Tkinter.Tk()

dnd = TkDND(root)

entry = Tkinter.Entry()
entry.config(width = 122, background = "black", foreground = "green", borderwidth = 5, selectforeground = "#fa4568", selectbackground = "black", insertbackground = "green", insertwidth = 1, relief = "flat", font = "{Segoe UI} 8")
entry.insert(0, "Trascinare e rilasciare (drag-and-drop) qui tutti i files .obj che si desidera convertire in .js ...")

def handle(event):
   os.system( 'cls' )
   inputfilespath = event.data
   event.widget.insert(0, inputfilespath)
   databases = filter(os.path.isfile, glob.glob('.\\*.obj'))
   for filename in databases:
      if os.path.isfile(filename) and filename.endswith(".obj"):
         event.widget.delete(0, Tkinter.END)
         print "\n\nPercorso assoluto del file di input:"
         print "\n"
         print filename
         subprocess1 = subprocess.Popen(['convert_obj_three.py', '-i', filename , '-o', filename +'.js'], shell=True)
         print "\n\nConversione in corso..."
         print "\n\nProcesso terminato:\n\nfile %s generato!" % filename +'.js'
          sys.stderr.write ('No .obj file found. Exiting program. \n')
      #    sys.exit(-1)
   event.widget.delete(0, Tkinter.END)
   event.widget.insert(0, "Processo terminato! ... Potete cominciare, se volete, un nuovo processo di conversione!")
#   sys.exit() # per uscire dal programma a fine conversione

dnd.bindtarget(entry, handle, 'text/uri-list')


But the problems which occur are:

    1) If .obj files are in a different folder respect to the convert_obj_three.py file, no conversion occurs (and this is a big problem)
    2) The script works if the .obj files are in the same folder of the convert_obj_three.py (for the conversion command) but, for example, if I drag and drop two of four .obj files, not only the two, but all the four files are converted...and so, this is another little problem
    3) If filename has a space, there is no conversion (so, this also would be nice if it were removed as problem), and process ends without even notify any error. "inputfilespath" wants to be the generic name for all the input files which I selected, and (for what I read) I can't use quotes for an environment variable hoping to include filename's whitespace...

I'm sure there is a solution somewhere nearby to achieve my purpose, as I see in many programs which usually you use...it's necessary only the right knowledge: I ask this to you for your experience and knowledge.

Thanks a lot for your time, help and explanations,

Last edited by micseydel on Mon Oct 21, 2013 2:26 am, edited 1 time in total.
Reason: First post lock.
User avatar
Posts: 3
Joined: Mon Oct 21, 2013 12:00 am
Location: Pisa (Italy)

Return to GUI

Who is online

Users browsing this forum: No registered users and 2 guests