[wxPython] Re: Sample code using drag & Drop with a tree

Re: Sample code using drag & Drop with a tree

Drag and Drop contributed by Sam Anderson, reposted by Dirk Krause

import string

from wxPython.wx import *

from xml.parsers import expat

try:

wxEVT_COMMAND_TREE_END_DRAG

except NameError:

# These got left out of 2.2.5, add them manually...

wxEVT_COMMAND_TREE_END_DRAG = 10617

def EVT_TREE_END_DRAG(win, id, func):

    win.Connect(id, -1, wxEVT_COMMAND_TREE_END_DRAG, func)

title = ‘wxTreeCtrl DragNDrop Test’

dummy xml file

xml=’’’<?xml version="1.0" encoding="UTF-8"?>

‘’’

class TestApp(wxApp):

def OnInit(self):

    # create navigation frame

    frame = NavFrame(NULL, -1, __title__)

    tree = frame.tree

    # expand a few nodes

    # NOTE: I know this is pathetic but I couldn't figure out how

    # to walk through and expand all nodes

    root = tree.nodeStack[0]

    child, cookie = tree.GetFirstChild(root, 0)

    nchild, cookie = tree.GetFirstChild(child, 0)

    tree.Expand(root)

    tree.Expand(child)

    tree.Expand(nchild)

    # display navigation frame

    frame.Show(true)

    self.SetTopWindow(frame)

    return true

class NavFrame(wxFrame):

def __init__(self, parent, ID, title):

    wxFrame.__init__(self, parent, ID, title,

       wxDefaultPosition,

       wxSize(270,500))

    # give the tree a unique id

    tID = NewId()

    # call the tree

    self.tree = XMLTree(self, tID, wxDefaultPosition, wxSize(270,490),

         wxTR_HAS_BUTTONS)# | wxTR_EDIT_LABELS)

    # Trees need an image list to do DnD...

    self.tree.SetImageList(self.MakeImageList())

    # Load XML into tree

    self.tree.LoadXML()

    #-------------Drag-N-Drop Event Handlers

    EVT_TREE_BEGIN_DRAG(self.tree, tID, self.OnBeginDrag)

    EVT_TREE_END_DRAG(self.tree, tID, self.OnEndDrag)

    # other events

    EVT_CLOSE(self, self.OnCloseWindow)

def OnBeginDrag(self, event):

    item = event.GetItem()

    if item != self.tree.GetRootItem():

        self.draggingItem = item

        event.Allow()

def OnEndDrag(self, evt):

    itemSrc = self.draggingItem

    itemDst = evt.GetItem()

    self.draggingItem = None

    if not itemDst.IsOk():

        print "Can't drag to here..."

        return

    text = self.tree.GetItemText(itemSrc)

    self.tree.AppendItem(itemDst, text)

    self.tree.Delete(itemSrc)

def OnCloseWindow(self, event):

    self.Destroy()

def MakeImageList(self):

    il = wxImageList(16, 16)

    bmp = wxBitmap("icon1.bmp", wxBITMAP_TYPE_BMP)

    il.Add(bmp)

    self.il = il

    return il

class XMLTree(wxTreeCtrl):

def __init__(self, parent, id, pos, size, style):

    wxTreeCtrl.__init__(self, parent, id, pos, size, style)

    # create nodeStack and add root node

    self.nodeStack = [self.AddRoot("My InfoSpace")]

def StartElement(self, name, attrs ):

    name = name.encode()

    id = self.AppendItem(self.nodeStack[-1], name)

    # for each element map xml attributes to an associated dictionary

    self.SetPyData(id, attrs)

    # set title of tree node based on element title attribute

    if attrs.has_key('title'):

        title = attrs['title']

        self.SetItemText(id, str(title))

    # add element to tree

    self.nodeStack.append(id)

def EndElement(self,  name ):

    self.nodeStack = self.nodeStack[:-1]

def CharacterData(self, data ):

    if string.strip(data):

        data = data.encode()

        self.AppendItem(self.nodeStack[-1], data)

def LoadXML(self):

    Parser = expat.ParserCreate()

    Parser.StartElementHandler = self.StartElement

    Parser.EndElementHandler = self.EndElement

    Parser.CharacterDataHandler = self.CharacterData

    ParserStatus = Parser.Parse(xml, 1)

if name == ‘main’:

app = TestApp(0)

app.MainLoop()

Dirk Krause

Beautiful!!!!

I didn't know that I must set an image list (wxImageList) to do Drag and
Drop (even though in my case I pass it with no bitmaps)

I just uncommented out A LOT of code
Thanks a lot

···

DirkK wrote:

# Drag and Drop contributed by Sam Anderson, reposted by Dirk Krause

import string

from wxPython.wx import *
from xml.parsers import expat

try:
    wxEVT_COMMAND_TREE_END_DRAG
except NameError:
    # These got left out of 2.2.5, add them manually...
    wxEVT_COMMAND_TREE_END_DRAG = 10617
    def EVT_TREE_END_DRAG(win, id, func):
        win.Connect(id, -1, wxEVT_COMMAND_TREE_END_DRAG, func)

__title__ = 'wxTreeCtrl DragNDrop Test'

# dummy xml file
xml='''<?xml version="1.0" encoding="UTF-8"?>
<Test title="Channels">
<Channels title="Favourites">
  <Channel type="channel" title="Slashdot" uri="http://slashdot.org"/>

</Channels>
<Channels title="News">
  <Channel title="CNN" uri="http://cnn.com"/>
  <Channel title="BBC" uri="http://bbc.co.uk"/>
  <Channel title="The Economist" uri="http://economist.com"/>
  <Channel title="MSNB" uri="http://msnbc.com"/>
</Channels>
<Channels title="Sports">
  <Channel type="channel" title="ESPN" uri="http://espn.com"/>
</Channels>
<Trash title="Trash"/>
</Test>'''

class TestApp(wxApp):

    def OnInit(self):

        # create navigation frame
        frame = NavFrame(NULL, -1, __title__)
        tree = frame.tree

        # expand a few nodes
        # NOTE: I know this is pathetic but I couldn't figure out how
        # to walk through and expand all nodes
        root = tree.nodeStack[0]
        child, cookie = tree.GetFirstChild(root, 0)
        nchild, cookie = tree.GetFirstChild(child, 0)
        tree.Expand(root)
        tree.Expand(child)
        tree.Expand(nchild)

        # display navigation frame
        frame.Show(true)
        self.SetTopWindow(frame)
        return true

class NavFrame(wxFrame):

    def __init__(self, parent, ID, title):
        wxFrame.__init__(self, parent, ID, title,
           wxDefaultPosition,
           wxSize(270,500))

        # give the tree a unique id
        tID = NewId()

        # call the tree
        self.tree = XMLTree(self, tID, wxDefaultPosition,
wxSize(270,490),
             wxTR_HAS_BUTTONS)# | wxTR_EDIT_LABELS)

        # Trees need an image list to do DnD...
        self.tree.SetImageList(self.MakeImageList())

        # Load XML into tree
        self.tree.LoadXML()

        #-------------Drag-N-Drop Event Handlers
        EVT_TREE_BEGIN_DRAG(self.tree, tID, self.OnBeginDrag)
        EVT_TREE_END_DRAG(self.tree, tID, self.OnEndDrag)

        # other events
        EVT_CLOSE(self, self.OnCloseWindow)

    def OnBeginDrag(self, event):
        item = event.GetItem()
        if item != self.tree.GetRootItem():
            self.draggingItem = item
            event.Allow()

    def OnEndDrag(self, evt):
        itemSrc = self.draggingItem
        itemDst = evt.GetItem()
        self.draggingItem = None

        if not itemDst.IsOk():
            print "Can't drag to here..."
            return

        text = self.tree.GetItemText(itemSrc)
        self.tree.AppendItem(itemDst, text)
        self.tree.Delete(itemSrc)

    def OnCloseWindow(self, event):
        self.Destroy()

    def MakeImageList(self):
        il = wxImageList(16, 16)
        bmp = wxBitmap("icon1.bmp", wxBITMAP_TYPE_BMP)
        il.Add(bmp)
        self.il = il
        return il

class XMLTree(wxTreeCtrl):

    def __init__(self, parent, id, pos, size, style):
        wxTreeCtrl.__init__(self, parent, id, pos, size, style)

        # create nodeStack and add root node
        self.nodeStack = [self.AddRoot("My InfoSpace")]

    def StartElement(self, name, attrs ):
        name = name.encode()

        id = self.AppendItem(self.nodeStack[-1], name)

        # for each element map xml attributes to an associated
dictionary
        self.SetPyData(id, attrs)

        # set title of tree node based on element title attribute
        if attrs.has_key('title'):
            title = attrs['title']
            self.SetItemText(id, str(title))

        # add element to tree
        self.nodeStack.append(id)

    def EndElement(self, name ):
        self.nodeStack = self.nodeStack[:-1]

    def CharacterData(self, data ):
        if string.strip(data):
            data = data.encode()
            self.AppendItem(self.nodeStack[-1], data)

    def LoadXML(self):
        Parser = expat.ParserCreate()

        Parser.StartElementHandler = self.StartElement
        Parser.EndElementHandler = self.EndElement
        Parser.CharacterDataHandler = self.CharacterData

        ParserStatus = Parser.Parse(xml, 1)

if __name__ == '__main__':
    app = TestApp(0)
    app.MainLoop()

Dirk Krause