wxPython: Dragging a file into window to get file path
Asked Answered
A

1

5

I want to drag a file into a window and get the file path. I've tried doing this:

class CSVDropper(wx.FileDropTarget):
  def __init__(self, data):
      wx.FileDropTarget.__init__(self)
      self.data = data

  def OnDropFiles(self, x, y, filenames):
      self.data = filenames
      print self.data

then in the main window:

    # Drag & Drop
    self.csv_path = None
    self.drop_table = CSVDropper(self.csv_path)

    self.SetDropTarget(self.drop_table)

But this does nothing. I've tried running this tutorial code, but it doesn't do anything either. How do I accomplish this?

Awning answered 13/7, 2015 at 19:9 Comment(3)
The variable names shouldn't matter. Nevertheless, I changed them. The results are still the same.Awning
I guess I'm being a bit naive. I think print will print the file path of the file that was drug into the window. I doubt that's actually what will happen. However, regardless of what is printed, I get something looking like the no smoking icon when I drag it over the window. I get the same thing when I try this in the demo I posted.Awning
Oh, self is a wx.Frame object. I want them to be able to drag and drop it into the window. Wherever is fine.Awning
T
11

When you print self.data, you should see a list of paths printed out. Anyway, I wrote up a tutorial on drag-n-drop a while ago which shows how to do this. Here's a slightly modified version of my code that both prints out the file paths to stdout and to a text control too:

import wx

########################################################################
class MyFileDropTarget(wx.FileDropTarget):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, window):
        """Constructor"""
        wx.FileDropTarget.__init__(self)
        self.window = window

    #----------------------------------------------------------------------
    def OnDropFiles(self, x, y, filenames):
        """
        When files are dropped, write where they were dropped and then
        the file paths themselves
        """
        self.window.SetInsertionPointEnd()
        self.window.updateText("\n%d file(s) dropped at %d,%d:\n" %
                              (len(filenames), x, y))
        print filenames
        for filepath in filenames:
            self.window.updateText(filepath + '\n')    

########################################################################
class DnDPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent=parent)

        file_drop_target = MyFileDropTarget(self)
        lbl = wx.StaticText(self, label="Drag some files here:")
        self.fileTextCtrl = wx.TextCtrl(self,
                                        style=wx.TE_MULTILINE|wx.HSCROLL|wx.TE_READONLY)
        self.fileTextCtrl.SetDropTarget(file_drop_target)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(lbl, 0, wx.ALL, 5)
        sizer.Add(self.fileTextCtrl, 1, wx.EXPAND|wx.ALL, 5)
        self.SetSizer(sizer)

    #----------------------------------------------------------------------
    def SetInsertionPointEnd(self):
        """
        Put insertion point at end of text control to prevent overwriting
        """
        self.fileTextCtrl.SetInsertionPointEnd()

    #----------------------------------------------------------------------
    def updateText(self, text):
        """
        Write text to the text control
        """
        self.fileTextCtrl.WriteText(text)

########################################################################
class DnDFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, parent=None, title="DnD Tutorial")
        panel = DnDPanel(self)
        self.Show()

#----------------------------------------------------------------------
if __name__ == "__main__":
    app = wx.App(False)
    frame = DnDFrame()
    app.MainLoop()
Tangelatangelo answered 13/7, 2015 at 20:59 Comment(8)
I tried running your code, and it still does not work. I drag some files from a windows explorer over the box, and I get the little circle with a line through it. I drop the file on the window and nothing happens. What could I be doing wrong?Awning
I don't know. What version of wxPython are you using and on what OS? I tested this code on Windows 7, Python 2.7.9 with wxPython 3.0.2.0. I also tested it on Xubuntu 14.04 with Python 2.7.6 and wxPython 2.8.12Tangelatangelo
Windows 7, Python 2.7.9, wxPython 2.8.12.1Awning
I'll try it on a co-workers computer and report back.Awning
The issue was I was running the tutorial file you gave me through an IDE using debug mode. That must have somehow blocked the file. My program is still not working, however. Are there certain restrictions on (object).SetDropTarget? Can it not be a wx.Frame? Can the frame be in a wx.Notebook?Or does it have to be a Control object?Awning
I GOT IT!: Apparently if you run the program through the PyCharm IDE, drag and drop is disabled somehow. By running the Compiled Python File directly I was able to get the desired effect!Awning
I guess that means that PyCharm doesn't run your script in a separate process. I would file a bug report with them. I tried it in my copy of PyCharm 4.5.2 and it worked though.Tangelatangelo
Let us continue this discussion in chat.Awning

© 2022 - 2024 — McMap. All rights reserved.