In order to improve usability, it is good to support drag and drop in an application so that the user can simply drop files or other objects into your application. This recipe will show how to support accepting a CompositeDataObject
that supports both files and text.
First we will define a custom drop target class:
class FileAndTextDropTarget(wx.PyDropTarget): """Drop target capable of accepting dropped files and text """ def __init__(self, file_callback, text_callback): assert callable(file_callback) assert callable(text_callback) super(FileAndTextDropTarget, self).__init__() # Attributes self.fcallback = file_callback # Drop File Callback self.tcallback = text_callback # Drop Text Callback self._data = None self.txtdo = None self.filedo = None # Setup self.InitObjects() def InitObjects(self): """Initializes the text and file data objects""" self._data = wx.DataObjectComposite() self.txtdo = wx.TextDataObject() self.filedo = wx.FileDataObject() self._data.Add(self.txtdo, False) self._data.Add(self.filedo, True) self.SetDataObject(self._data) def OnData(self, x_cord, y_cord, drag_result): """Called by the framework when data is dropped on the target """ if self.GetData(): data_format = self._data.GetReceivedFormat() if data_format.GetType() == wx.DF_FILENAME: self.fcallback(self.filedo.GetFilenames()) else: self.tcallback(self.txtdo.GetText()) return drag_result
Then to make use of the FileAndTextDropTarget
, we assign it to a window using the window object's SetDropTarget
method.
class DropTargetFrame(wx.Frame): def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="DropTargetFrame"): super(DropTargetFrame, self).__init__(parent, id, title, pos, size, style, name) # Attributes choices = ["Drag and Drop Text or Files here",] self.list = wx.ListBox(self, choices=choices) self.dt = FileAndTextDropTarget(self.OnFileDrop, self.OnTextDrop) self.list.SetDropTarget(self.dt) # Setup self.CreateStatusBar() def OnFileDrop(self, files): self.PushStatusText("Files Dropped") for f in files: self.list.Append(f) def OnTextDrop(self, text): self.PushStatusText("Text Dropped") self.list.Append(txt)
The framework will call the OnData
method of our DropTarget
when the window has received the drop data. When OnData
is called, we simply get the data from our DataObject
and pass it to the appropriate callback function to let our window decide how to handle the data.
All window objects have a SetDropTarget
method that can be used to assign a DropTarget
, so this class can be reused for almost any type of control. In the previous example, we assigned it to a ListBox
and then appended the dropped data to the list in each of our callbacks.
The PyDropTarget
class provides a few more methods that can be called at different times during the drag operation. These methods can also be overridden in order to do things such as change the mouse cursor, show a custom drag image, or reject the drag object.
Methods |
When the methods are called |
---|---|
Called when a drag object enters the window. Returns a drag result value (that is, | |
Called while the mouse is dragging the object over the target | |
Called when the mouse leaves the drop target | |
Called when the user drops the object. Return | |
Called after |