Differences between revisions 5 and 6
Revision 5 as of 2001-12-28 18:32:45
Size: 4055
Editor: anonymous
Comment: missing edit-log entry for this revision
Revision 6 as of 2003-06-06 19:28:07
Size: 10614
Editor: anonymous
Comment: missing edit-log entry for this revision
Deletions are marked like this. Additions are marked like this.
Line 95: Line 95:
{{{
# A very simple Drag and Drop Example
# provided with no warranty whatsoever for any purpose, ever

# This code creates a Text Control from which Text can be dragged,
# a Text Control to which Text can be dragged (from the first Text Control or from other applications),
# and a Text Control to which Files can be dragged from outside this application.
# While the later two windows can receive data from outside the application, the first window
# does not appear to be able to provide text to other applications. Please feel free to fix
# this if you know how, as I think that would be more useful as an example.

# It is designed to demonstrate the fundamentals of very simple drag-and-drop operations.

""" This mini-ap is designed to demonstrate simple Drag and Drop functioning in wxPython """

__author__ = 'David Woods, Wisconsin Center for Education Research <dwoods@wcer.wisc.edu>'

# Import wxPython
from wxPython.wx import *

# Declare GUI Constants
MENU_FILE_EXIT = 101
DRAG_SOURCE = 201

# Define Text Drop Target class
class TextDropTarget(wxTextDropTarget):
   """ This object implements Drop Target functionality for Text """
   def __init__(self, obj):
      """ Initialize the Drop Target, passing in the Object Reference to
          indicate what should receive the dropped text """
      # Initialize the wxTextDropTarget Object
      wxTextDropTarget.__init__(self)
      # Store the Object Reference for dropped text
      self.obj = obj

   def OnDropText(self, x, y, data):
      """ Implement Text Drop """
      # When text is dropped, write it into the object specified
      self.obj.WriteText(data + '\n\n')

# Define File Drop Target class
class FileDropTarget(wxFileDropTarget):
   """ This object implements Drop Target functionality for Files """
   def __init__(self, obj):
      """ Initialize the Drop Target, passing in the Object Reference to
          indicate what should receive the dropped files """
      # Initialize the wsFileDropTarget Object
      wxFileDropTarget.__init__(self)
      # Store the Object Reference for dropped files
      self.obj = obj

   def OnDropFiles(self, x, y, filenames):
      """ Implement File Drop """
      # For Demo purposes, this function appends a list of the files dropped at the end of the widget's text
      # Move Insertion Point to the end of the widget's text
      self.obj.SetInsertionPointEnd()
      # append a list of the file names dropped
      self.obj.WriteText("%d file(s) dropped at %d, %d:\n" % (len(filenames), x, y))
      for file in filenames:
         self.obj.WriteText(file + '\n')
      self.obj.WriteText('\n')



class MainWindow(wxFrame):
   """ This window displays the GUI Widgets. """
   def __init__(self,parent,id,title):
       wxFrame.__init__(self,parent,-4, title, size = (800,600), style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
       self.SetBackgroundColour(wxWHITE)

       # Menu Bar
       # Create a MenuBar
       menuBar = wxMenuBar()
       # Build a Menu Object to go into the Menu Bar
       menu1 = wxMenu()
       menu1.Append(MENU_FILE_EXIT, "E&xit", "Quit Application")
       # Place the Menu Item in the Menu Bar
       menuBar.Append(menu1, "&File")
       # Place the Menu Bar on the ap
       self.SetMenuBar(menuBar)
       #Define Events for the Menu Items
       EVT_MENU(self, MENU_FILE_EXIT, self.CloseWindow)

       # GUI Widgets
       # Define a Text Control from which Text can be dragged for dropping
       # Label the control
       wxStaticText(self, -1, "Text Drag Source (left-click to select, right-click to drag)", (10, 1))
       # Create a Text Control
       self.text = wxTextCtrl(self, DRAG_SOURCE, "", pos=(10,15), size=(350,500), style = wxTE_MULTILINE|wxHSCROLL)
       # Make this control a Text Drop Target
       # Create a Text Drop Target object
       dt1 = TextDropTarget(self.text)
       # Link the Drop Target Object to the Text Control
       self.text.SetDropTarget(dt1)
       # Put some text in the control as a starting place to have something to copy
       for x in range(20):
          self.text.WriteText("This is line %d of some text to drag.\n" % x)
       # Define Right-Click as start of Drag
       EVT_RIGHT_DOWN(self.text, self.OnDragInit)

       # Define a Text Control to recieve Dropped Text
       # Label the control
       wxStaticText(self, -1, "Text Drop Target", (370, 1))
       # Create a read-only Text Control
       self.text2 = wxTextCtrl(self, -1, "", pos=(370,15), size=(410,235), style = wxTE_MULTILINE|wxHSCROLL|wxTE_READONLY)
       # Make this control a Text Drop Target
       # Create a Text Drop Target object
       dt2 = TextDropTarget(self.text2)
       # Link the Drop Target Object to the Text Control
       self.text2.SetDropTarget(dt2)

       # Define a Text Control to recieve Dropped Files
       # Label the control
       wxStaticText(self, -1, "File Drop Target (from off application only)", (370, 261))
       # Create a read-only Text Control
       self.text3 = wxTextCtrl(self, -1, "", pos=(370,275), size=(410,235), style = wxTE_MULTILINE|wxHSCROLL|wxTE_READONLY)
       # Make this control a File Drop Target
       # Create a File Drop Target object
       dt3 = FileDropTarget(self.text3)
       # Link the Drop Target Object to the Text Control
       self.text3.SetDropTarget(dt3)

       # Display the Window
       self.Show(true)


   def CloseWindow(self, event):
       """ Close the Window """
       self.Close()

   def OnDragInit(self, event):
       """ Begin a Drag Operation """
       # Create a Text Data Object, which holds the text that is to be dragged
       tdo = wxPyTextDataObject(self.text.GetStringSelection())
       # Create a Drop Source Object, which enables the Drag operation
       tds = wxDropSource(self.text)
       # Associate the Data to be dragged with the Drop Source Object
       tds.SetData(tdo)
       # Intiate the Drag Operation
       tds.DoDragDrop(wx.true)



class MyApp(wxApp):
   """ Define the Drag and Drop Example Application """
   def OnInit(self):
      """ Initialize the Application """
      # Declare the Main Application Window
      frame = MainWindow(None, -1, "Drag and Drop Example")
      # Show the Application as the top window
      self.SetTopWindow(frame)
      return true
      

# Declare the Application and start the Main Loop
app = MyApp(0)
app.MainLoop()
}}}

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

# A very simple Drag and Drop Example
# provided with no warranty whatsoever for any purpose, ever

# This code creates a Text Control from which Text can be dragged,
# a Text Control to which Text can be dragged (from the first Text Control or from other applications),
# and a Text Control to which Files can be dragged from outside this application.
# While the later two windows can receive data from outside the application, the first window
# does not appear to be able to provide text to other applications.  Please feel free to fix
# this if you know how, as I think that would be more useful as an example.

# It is designed to demonstrate the fundamentals of very simple drag-and-drop operations.

""" This mini-ap is designed to demonstrate simple Drag and Drop functioning in wxPython """

__author__ = 'David Woods, Wisconsin Center for Education Research <dwoods@wcer.wisc.edu>'

# Import wxPython
from wxPython.wx import *

# Declare GUI Constants
MENU_FILE_EXIT = 101
DRAG_SOURCE    = 201

# Define Text Drop Target class
class TextDropTarget(wxTextDropTarget):
   """ This object implements Drop Target functionality for Text """
   def __init__(self, obj):
      """ Initialize the Drop Target, passing in the Object Reference to
          indicate what should receive the dropped text """
      # Initialize the wxTextDropTarget Object
      wxTextDropTarget.__init__(self)
      # Store the Object Reference for dropped text
      self.obj = obj

   def OnDropText(self, x, y, data):
      """ Implement Text Drop """
      # When text is dropped, write it into the object specified
      self.obj.WriteText(data + '\n\n')

# Define File Drop Target class
class FileDropTarget(wxFileDropTarget):
   """ This object implements Drop Target functionality for Files """
   def __init__(self, obj):
      """ Initialize the Drop Target, passing in the Object Reference to
          indicate what should receive the dropped files """
      # Initialize the wsFileDropTarget Object
      wxFileDropTarget.__init__(self)
      # Store the Object Reference for dropped files
      self.obj = obj

   def OnDropFiles(self, x, y, filenames):
      """ Implement File Drop """
      # For Demo purposes, this function appends a list of the files dropped at the end of the widget's text
      # Move Insertion Point to the end of the widget's text
      self.obj.SetInsertionPointEnd()
      # append a list of the file names dropped
      self.obj.WriteText("%d file(s) dropped at %d, %d:\n" % (len(filenames), x, y))
      for file in filenames:
         self.obj.WriteText(file + '\n')
      self.obj.WriteText('\n')



class MainWindow(wxFrame):
   """ This window displays the GUI Widgets. """
   def __init__(self,parent,id,title):
       wxFrame.__init__(self,parent,-4, title, size = (800,600), style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
       self.SetBackgroundColour(wxWHITE)

       # Menu Bar
       # Create a MenuBar
       menuBar = wxMenuBar()
       # Build a Menu Object to go into the Menu Bar
       menu1 = wxMenu()
       menu1.Append(MENU_FILE_EXIT, "E&xit", "Quit Application")
       # Place the Menu Item in the Menu Bar
       menuBar.Append(menu1, "&File")
       # Place the Menu Bar on the ap
       self.SetMenuBar(menuBar)
       #Define Events for the Menu Items
       EVT_MENU(self, MENU_FILE_EXIT, self.CloseWindow)

       # GUI Widgets
       # Define a Text Control from which Text can be dragged for dropping
       # Label the control
       wxStaticText(self, -1, "Text Drag Source  (left-click to select, right-click to drag)", (10, 1))
       # Create a Text Control
       self.text = wxTextCtrl(self, DRAG_SOURCE, "", pos=(10,15), size=(350,500), style = wxTE_MULTILINE|wxHSCROLL)
       # Make this control a Text Drop Target
       # Create a Text Drop Target object
       dt1 = TextDropTarget(self.text)
       # Link the Drop Target Object to the Text Control
       self.text.SetDropTarget(dt1)
       # Put some text in the control as a starting place to have something to copy
       for x in range(20):
          self.text.WriteText("This is line %d of some text to drag.\n" % x)
       # Define Right-Click as start of Drag
       EVT_RIGHT_DOWN(self.text, self.OnDragInit)

       # Define a Text Control to recieve Dropped Text
       # Label the control
       wxStaticText(self, -1, "Text Drop Target", (370, 1))
       # Create a read-only Text Control
       self.text2 = wxTextCtrl(self, -1, "", pos=(370,15), size=(410,235), style = wxTE_MULTILINE|wxHSCROLL|wxTE_READONLY)
       # Make this control a Text Drop Target
       # Create a Text Drop Target object
       dt2 = TextDropTarget(self.text2)
       # Link the Drop Target Object to the Text Control
       self.text2.SetDropTarget(dt2)

       # Define a Text Control to recieve Dropped Files
       # Label the control
       wxStaticText(self, -1, "File Drop Target (from off application only)", (370, 261))
       # Create a read-only Text Control
       self.text3 = wxTextCtrl(self, -1, "", pos=(370,275), size=(410,235), style = wxTE_MULTILINE|wxHSCROLL|wxTE_READONLY)
       # Make this control a File Drop Target
       # Create a File Drop Target object
       dt3 = FileDropTarget(self.text3)
       # Link the Drop Target Object to the Text Control
       self.text3.SetDropTarget(dt3)

       # Display the Window
       self.Show(true)


   def CloseWindow(self, event):
       """ Close the Window """
       self.Close()

   def OnDragInit(self, event):
       """ Begin a Drag Operation """
       # Create a Text Data Object, which holds the text that is to be dragged
       tdo = wxPyTextDataObject(self.text.GetStringSelection())
       # Create a Drop Source Object, which enables the Drag operation
       tds = wxDropSource(self.text)
       # Associate the Data to be dragged with the Drop Source Object
       tds.SetData(tdo)
       # Intiate the Drag Operation
       tds.DoDragDrop(wx.true)



class MyApp(wxApp):
   """ Define the Drag and Drop Example Application """
   def OnInit(self):
      """ Initialize the Application """
      # Declare the Main Application Window
      frame = MainWindow(None, -1, "Drag and Drop Example")
      # Show the Application as the top window
      self.SetTopWindow(frame)
      return true
      

# Declare the Application and start the Main Loop
app = MyApp(0)
app.MainLoop()
  • 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


DragAndDrop (last edited 2012-06-05 19:58:29 by pool-71-175-100-238)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.