Wednesday, April 10, 2013

Drag and drop in wxPython

Drag and drop in wxPython

Wikipedia: In computer graphical user interfaces, drag-and-drop is the action of (or support for the action of) clicking on a virtual object and dragging it to a different location or onto another virtual object. In general, it can be used to invoke many kinds of actions, or create various types of associations between two abstract objects.
Drag and drop functionality is one of the most visible aspects of the graphical user interface. Drag and drop operation enables you to do complex things intuitively.
In drag and drop we basically drag some data from a data source to a data target. So we must have:
  • Some data
  • A data source
  • A data target
In wxPython we have two predefined data targets. wx.TextDropTarget and wx.FileDropTarget.
  • wx.TextDropTarget
  • wx.FileDropTarget

wx.TextDropTarget

Text drag and drop
Figure: dragdrop.py

#!/usr/bin/python

# dragdrop.py

import os
import wx

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)


class DragDrop(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(650, 500))

splitter1 = wx.SplitterWindow(self, -1, style=wx.SP_3D)
splitter2 = wx.SplitterWindow(splitter1, -1, style=wx.SP_3D)
self.dir = wx.GenericDirCtrl(splitter1, -1, dir='/home/', style=wx.DIRCTRL_DIR_ONLY)
self.lc1 = wx.ListCtrl(splitter2, -1, style=wx.LC_LIST)
self.lc2 = wx.ListCtrl(splitter2, -1, style=wx.LC_LIST)

dt = MyTextDropTarget(self.lc2)
self.lc2.SetDropTarget(dt)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.OnDragInit, id=self.lc1.GetId())

tree = self.dir.GetTreeCtrl()

splitter2.SplitHorizontally(self.lc1, self.lc2)
splitter1.SplitVertically(self.dir, splitter2)

self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelect, id=tree.GetId())

self.OnSelect(0)
self.Centre()
self.Show(True)

def OnSelect(self, event):
list = os.listdir(self.dir.GetPath())
self.lc1.ClearAll()
self.lc2.ClearAll()
for i in range(len(list)):
if list[i][0] != '.':
self.lc1.InsertStringItem(0, list[i])

def OnDragInit(self, event):
text = self.lc1.GetItemText(event.GetIndex())
tdo = wx.TextDataObject(text)
tds = wx.DropSource(self.lc1)
tds.SetData(tdo)
tds.DoDragDrop(True)


app = wx.App()
DragDrop(None, -1, 'dragdrop.py')
app.MainLoop()

wx.FileDropTarget

One of the advantages of the GUI over the console is it's intuitiveness. You can learn a GUI program easier than a console application. You often do not need a manual. On the other hand, some graphical operations are too complex. For example, deleting a file by dragging it and droping it to the trash basket is very intuitive and easy to understand, but actually most people just press the delete key. (shift + delete) It is more effective. In our next example we explore a graphical operation, that is very handy. In most GUI text editors, you can open a file by simply dragging it from the file manager and dropping it on the editor.
#!/usr/bin/python

# filedrop.py

import wx

class FileDrop(wx.FileDropTarget):
def __init__(self, window):
wx.FileDropTarget.__init__(self)
self.window = window

def OnDropFiles(self, x, y, filenames):

for name in filenames:
try:
file = open(name, 'r')
text = file.read()
self.window.WriteText(text)
file.close()
except IOError, error:
dlg = wx.MessageDialog(None, 'Error opening file\n' + str(error))
dlg.ShowModal()
except UnicodeDecodeError, error:
dlg = wx.MessageDialog(None, 'Cannot open non ascii files\n' + str(error))
dlg.ShowModal()

class DropFile(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size = (450, 400))

self.text = wx.TextCtrl(self, -1, style = wx.TE_MULTILINE)
dt = FileDrop(self.text)
self.text.SetDropTarget(dt)
self.Centre()
self.Show(True)


app = wx.App()
DropFile(None, -1, 'filedrop.py')
app.MainLoop()
This chapter described shortly drag and drop operations in wxPython.

No comments:

Post a Comment