wxPython - Arrastrar y soltar

Provisión de drag and dropes muy intuitivo para el usuario. Se encuentra en muchas aplicaciones de escritorio donde el usuario puede copiar o mover objetos de una ventana a otra con solo arrastrarlo con el mouse y soltarlo en otra ventana.

La operación de arrastrar y soltar implica los siguientes pasos:

  • Declarar un objetivo de caída
  • Crear objeto de datos
  • Crear wx.DropSource
  • Ejecutar operación de arrastre
  • Cancelar o aceptar drop

En wxPython, hay dos destinos de colocación predefinidos:

  • wx.TextDropTarget
  • wx.FileDropTarget

Muchos widgets de wxPython admiten la actividad de arrastrar y soltar. El control de origen debe tener habilitado el arrastre, mientras que el control de destino debe estar en posición de aceptar (o rechazar) el arrastre.

Los datos de origen que el usuario arrastra se colocan en el objeto de destino. OnDropText () del objeto de destino consume los datos. Si lo desea, se pueden eliminar los datos del objeto de origen.

Ejemplo

En el siguiente ejemplo, dos objetos ListCrl se colocan horizontalmente en un Box Sizer. La lista de la izquierda se completa con datos de idiomas []. Está designado como fuente de arrastre. Uno a la derecha es el objetivo.

languages = ['C', 'C++', 'Java', 'Python', 'Perl', 'JavaScript', 'PHP', 'VB.NET','C#'] 
self.lst1 = wx.ListCtrl(panel, -1, style = wx.LC_LIST) 
self.lst2 = wx.ListCtrl(panel, -1, style = wx.LC_LIST) 

   for lang in languages: 
      self.lst1.InsertStringItem(0,lang)

El segundo control de lista está vacío y es un argumento para el objeto de la clase TextDropTarget.

class MyTextDropTarget(wx.TextDropTarget):
   def __init__(self, object): 
      wx.TextDropTarget.__init__(self) 
      self.object = object
		
   def OnDropText(self, x, y, data): 
      self.object.InsertStringItem(0, data)

El método OnDropText () agrega datos de origen en el control de la lista de destino.

La operación de arrastre es inicializada por el archivador de eventos.

wx.EVT_LIST_BEGIN_DRAG(self, self.lst1.GetId(), self.OnDragInit)

La función OnDragInit () coloca los datos de arrastre en el destino y los elimina del origen.

def OnDragInit(self, event): 
   text = self.lst1.GetItemText(event.GetIndex()) 
   tobj = wx.PyTextDataObject(text) 
   src = wx.DropSource(self.lst1) 
   src.SetData(tobj) 
   src.DoDragDrop(True) 
   self.lst1.DeleteItem(event.GetIndex())

El código completo es el siguiente:

import wx
  
class MyTarget(wx.TextDropTarget): 
   def __init__(self, object): 
      wx.TextDropTarget.__init__(self) 
      self.object = object  
		
   def OnDropText(self, x, y, data): 
      self.object.InsertStringItem(0, data)  
		
class Mywin(wx.Frame): 
            
   def __init__(self, parent, title): 
      super(Mywin, self).__init__(parent, title = title,size = (-1,300))   
      panel = wx.Panel(self) 
      box = wx.BoxSizer(wx.HORIZONTAL)  
      languages = ['C', 'C++', 'Java', 'Python', 'Perl', 'JavaScript',
         'PHP', 'VB.NET','C#']
			
      self.lst1 = wx.ListCtrl(panel, -1, style = wx.LC_LIST) 
      self.lst2 = wx.ListCtrl(panel, -1, style = wx.LC_LIST) 
      for lang in languages: 
      self.lst1.InsertStringItem(0,lang) 
             
      dt = MyTarget(self.lst2) 
      self.lst2.SetDropTarget(dt) 
      wx.EVT_LIST_BEGIN_DRAG(self, self.lst1.GetId(), self.OnDragInit)
		
      box.Add(self.lst1,0,wx.EXPAND) 
      box.Add(self.lst2, 1, wx.EXPAND) 
		
      panel.SetSizer(box) 
      panel.Fit() 
      self.Centre() 
      self.Show(True)  
     
   def OnDragInit(self, event): 
      text = self.lst1.GetItemText(event.GetIndex()) 
      tobj = wx.PyTextDataObject(text) 
      src = wx.DropSource(self.lst1) 
      src.SetData(tobj) 
      src.DoDragDrop(True) 
      self.lst1.DeleteItem(event.GetIndex()) 
		
ex = wx.App() 
Mywin(None,'Drag&Drop Demo') 
ex.MainLoop()

El código anterior produce la siguiente salida: