File dropping in wxPython

As an exercise in learning Python, I decided to write a picture viewer, using wxPython, an app with some features I rarely see and wanted. I had done the same exercise earlier this year with C#/WPF, this went well, but doesn't work on our home Mac. The python version will.

Things have been going well. I did have a bit of a surprise when I added the possibility to drop files onto an open picture viewer. In C#/WPF, this is a simple event, like clicking a button. But in wxPython, one needs to instanciate a new class, wx.FileDropTarget, to do this.

All examples I found on the Web did this using two separate objects, so there was a need to have them communicate. But I thought, why not do them in the same object? This gave me the following code (but see CAUTION below):

import wx

class DropApp(wx.Frame, wx.FileDropTarget): # two parent classes
   def __init__(self):
      self.app = wx.App()
      wx.Frame.__init__(self, parent=None, title='DropFile', size=(400, 250))
      wx.FileDropTarget.__init__(self)
      self.SetDropTarget(self)    # connecting the two parent classes :-)

   def OnDropFiles(self, x, y, names):  # overriding method from wx.FileDropTarget
      print 'File dropped(' + str(type(names[0])) + '): ' + str(names)
      # process the file names in the context of the wx.Frame app !

   def run(self):
      self.Show()
      self.app.MainLoop()

app = DropApp()
app.run()
It seems to work fine in my picture viewer.

CAUTION: That was in wxPython 3. I have now upgraded to wxPython 4, and the above crashes. So it's probably not a good idea!

The following is probably closer to how it should be done:

from __future__ import print_function

import wx
print('wx.VERSION=', wx.VERSION)

class Dropper(wx.FileDropTarget):

   def __init__(self, target):
      wx.FileDropTarget.__init__(self)
      self.target = target

   def OnDropFiles(self, x, y, names):
      return self.target.OnDropFiles(names)

class DropApp(wx.Frame):

   def __init__(self):
      self.app = wx.App()
      wx.Frame.__init__(self, parent=None, title='DropFile', size=(400, 250))
      self.SetDropTarget(Dropper(self))

   def OnDropFiles(self, names):
      print('class DropApp : file dropped(' + str(type(names[0])) + '): ' + str(names))
      # process the file names in the context of the wx.Frame app !
      return True

   def run(self):
      self.Show()
      self.app.MainLoop()

app = DropApp()
app.run()

I guess I was trying to be too smart... I have recently read that multiple inheritance of wxPython classes is not recommended !

Meta

To all folks who provide snippets of code as example: please keep it simple and include only as much code as needed to make the snippet work for the thing you're talking about, but not more. I just want to grok the gist of the mechanism, I don't need to see all the GUI stuff that makes a complete application, in particular no need for sizers, panels, buttons, whatever. I already have all that in my application. I just need to understand enough to be able to integrate it in my code, no more.

Similarly for error handling. Maybe the text should name the important exceptions, but I don't need that in the example.

Home. Email:  (français, English, Deutsch).