Introduction
- Drag and drop support within wxPython is a conversation between a "drop source" and a "drop target". The conversation is accomplished by sharing a "data object" which includes certain pieces of metadata (primarily the data types available from the drop source) as well as the actual shared data.
What Objects are Involved
- Source window -- Interprets an event as the beginning of a new drag-and-drop request. Instantiates a new drop source
and triggers the drag-and-drop sequence by calling DoDragDrop on the drop source object. Responds to the result code of the drag-and-drop sequence (move/copy/cancel/fail).
wxDropSource -- Provides common functionality for drag-and-drop source windows (UI interactions, data object storage)
- Destination window -- Advertises acceptable data types by
calling SetDropTarget with a configured drop target object.
wxDropTarget -- Responds to various "pseudo-events" during the drag-and-drop process, most importantly the OnData "event" which indicates that an object has been dropped on the associated window.
wxDataObject -- Provides storage and metadata relating to the data being transferred during a drag-and-drop operation. May support one of the built-in data types (text, bitmap, file), a single declared data type, or multiple data types. Includes: wxTextDataObject, wxBitmapDataObject, wxFileDataObject, wxDataObjectSimple, wxDataObjectComposite, wxDataObject
Process Overview
Create or choose a wxDataObject subclass appropriate to the data being shared
Provide OnData method to handle incoming data and update your application with the results of the drag-and-drop operation.
- If you are not using a built-in data type, choose a type specifier (a unique string used to identify the datatype). Only targets whose type specifiers include one of the current data source specifiers will be eligible for drops.
Create a wxPyDropTarget subclass (and instance)
Provide an OnData method to handle a drop "event"
Call self.GetData() to transfer data to the target's wxDataObject instance
Call wxDataObject.GetData() to retrieve the actual shared data
- Update your application to reflect drag-and-drop operation (in many cases you will need a pointer to the target window within the drop target instance to accomplish this).
Instantiate an instance of your wxDataObject class
Bind a wxDataObject to the drop target by calling SetDataObject. You will also want to keep a pointer to the wxDataObject in the drop target instance, so that you can call wxDataObject.GetData() within the OnData method.
Bind the drop target to the target window using wxWindow.SetDropTarget
- Handle an event on the source window which signals the start of the drag-and-drop cycle
Create a wxDropSource
Set the data object of the drop source to another instance of your wxDataObject class
Call the drop source DoDragDrop() method to begin the drag-and-drop operation
Respond to the result code of the DoDragDrop method as appropriate to your application
wxDataObjects
- Discuss the various concerns relating to the data object. Python pickling options Multiple formats -- currently only works for source in Python (as far as I can see) Format specifiers, do these need to be discussed? Special Data Types
Code Samples
- Simple drag-and-drop
1 # A very simple Drag and Drop Example
2 # provided with no warranty whatsoever for any purpose, ever
3
4 # This code creates a Text Control from which Text can be dragged,
5 # a Text Control to which Text can be dragged (from the first Text Control or from other applications),
6 # and a Text Control to which Files can be dragged from outside this application.
7 # While the later two windows can receive data from outside the application, the first window
8 # does not appear to be able to provide text to other applications. Please feel free to fix
9 # this if you know how, as I think that would be more useful as an example.
10
11 # It is designed to demonstrate the fundamentals of very simple drag-and-drop operations.
12
13 """ This mini-ap is designed to demonstrate simple Drag and Drop functioning in wxPython """
14
15 __author__ = 'David Woods, Wisconsin Center for Education Research <dwoods@wcer.wisc.edu>'
16
17 # Import wxPython
18 from wxPython.wx import *
19
20 # Declare GUI Constants
21 MENU_FILE_EXIT = 101
22 DRAG_SOURCE = 201
23
24 # Define Text Drop Target class
25 class TextDropTarget(wxTextDropTarget):
26 """ This object implements Drop Target functionality for Text """
27 def __init__(self, obj):
28 """ Initialize the Drop Target, passing in the Object Reference to
29 indicate what should receive the dropped text """
30 # Initialize the wxTextDropTarget Object
31 wxTextDropTarget.__init__(self)
32 # Store the Object Reference for dropped text
33 self.obj = obj
34
35 def OnDropText(self, x, y, data):
36 """ Implement Text Drop """
37 # When text is dropped, write it into the object specified
38 self.obj.WriteText(data + '\n\n')
39
40 # Define File Drop Target class
41 class FileDropTarget(wxFileDropTarget):
42 """ This object implements Drop Target functionality for Files """
43 def __init__(self, obj):
44 """ Initialize the Drop Target, passing in the Object Reference to
45 indicate what should receive the dropped files """
46 # Initialize the wsFileDropTarget Object
47 wxFileDropTarget.__init__(self)
48 # Store the Object Reference for dropped files
49 self.obj = obj
50
51 def OnDropFiles(self, x, y, filenames):
52 """ Implement File Drop """
53 # For Demo purposes, this function appends a list of the files dropped at the end of the widget's text
54 # Move Insertion Point to the end of the widget's text
55 self.obj.SetInsertionPointEnd()
56 # append a list of the file names dropped
57 self.obj.WriteText("%d file(s) dropped at %d, %d:\n" % (len(filenames), x, y))
58 for file in filenames:
59 self.obj.WriteText(file + '\n')
60 self.obj.WriteText('\n')
61
62
63
64 class MainWindow(wxFrame):
65 """ This window displays the GUI Widgets. """
66 def __init__(self,parent,id,title):
67 wxFrame.__init__(self,parent,-4, title, size = (800,600), style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
68 self.SetBackgroundColour(wxWHITE)
69
70 # Menu Bar
71 # Create a MenuBar
72 menuBar = wxMenuBar()
73 # Build a Menu Object to go into the Menu Bar
74 menu1 = wxMenu()
75 menu1.Append(MENU_FILE_EXIT, "E&xit", "Quit Application")
76 # Place the Menu Item in the Menu Bar
77 menuBar.Append(menu1, "&File")
78 # Place the Menu Bar on the ap
79 self.SetMenuBar(menuBar)
80 #Define Events for the Menu Items
81 EVT_MENU(self, MENU_FILE_EXIT, self.CloseWindow)
82
83 # GUI Widgets
84 # Define a Text Control from which Text can be dragged for dropping
85 # Label the control
86 wxStaticText(self, -1, "Text Drag Source (left-click to select, right-click to drag)", (10, 1))
87 # Create a Text Control
88 self.text = wxTextCtrl(self, DRAG_SOURCE, "", pos=(10,15), size=(350,500), style = wxTE_MULTILINE|wxHSCROLL)
89 # Make this control a Text Drop Target
90 # Create a Text Drop Target object
91 dt1 = TextDropTarget(self.text)
92 # Link the Drop Target Object to the Text Control
93 self.text.SetDropTarget(dt1)
94 # Put some text in the control as a starting place to have something to copy
95 for x in range(20):
96 self.text.WriteText("This is line %d of some text to drag.\n" % x)
97 # Define Right-Click as start of Drag
98 EVT_RIGHT_DOWN(self.text, self.OnDragInit)
99
100 # Define a Text Control to recieve Dropped Text
101 # Label the control
102 wxStaticText(self, -1, "Text Drop Target", (370, 1))
103 # Create a read-only Text Control
104 self.text2 = wxTextCtrl(self, -1, "", pos=(370,15), size=(410,235), style = wxTE_MULTILINE|wxHSCROLL|wxTE_READONLY)
105 # Make this control a Text Drop Target
106 # Create a Text Drop Target object
107 dt2 = TextDropTarget(self.text2)
108 # Link the Drop Target Object to the Text Control
109 self.text2.SetDropTarget(dt2)
110
111 # Define a Text Control to recieve Dropped Files
112 # Label the control
113 wxStaticText(self, -1, "File Drop Target (from off application only)", (370, 261))
114 # Create a read-only Text Control
115 self.text3 = wxTextCtrl(self, -1, "", pos=(370,275), size=(410,235), style = wxTE_MULTILINE|wxHSCROLL|wxTE_READONLY)
116 # Make this control a File Drop Target
117 # Create a File Drop Target object
118 dt3 = FileDropTarget(self.text3)
119 # Link the Drop Target Object to the Text Control
120 self.text3.SetDropTarget(dt3)
121
122 # Display the Window
123 self.Show(true)
124
125
126 def CloseWindow(self, event):
127 """ Close the Window """
128 self.Close()
129
130 def OnDragInit(self, event):
131 """ Begin a Drag Operation """
132 # Create a Text Data Object, which holds the text that is to be dragged
133 tdo = wxPyTextDataObject(self.text.GetStringSelection())
134 # Create a Drop Source Object, which enables the Drag operation
135 tds = wxDropSource(self.text)
136 # Associate the Data to be dragged with the Drop Source Object
137 tds.SetData(tdo)
138 # Intiate the Drag Operation
139 tds.DoDragDrop(True)
140
141
142
143 class MyApp(wxApp):
144 """ Define the Drag and Drop Example Application """
145 def OnInit(self):
146 """ Initialize the Application """
147 # Declare the Main Application Window
148 frame = MainWindow(None, -1, "Drag and Drop Example")
149 # Show the Application as the top window
150 self.SetTopWindow(frame)
151 return true
152
153
154 # Declare the Application and start the Main Loop
155 app = MyApp(0)
156 app.MainLoop()
- David K. Woods, Wisconsin Center for Education Research, University of Wisconsin, Madison
(If you like this example, there's another, more complex example of Drag and Drop behavior in the ListAndTreeControls section.)
- File/bitmap/text
Comments...
I will add a example for dragging items in a wxTreeCtrl and what is more interresting how to drag a branch in a wxTreeCtrl. if added it will be found under ListAndTreeControls.
--René Freund