I am building a program that will store some complex objects, and I am using wxPython for the UI. The objects hierarchy will have a tree representation (TreeCtrl
). I am using a dictionary to map objects from the UI to the database, using the TreeItemId
s returned by AppendItem
as keys and the objects themselves as values (actually I am not using the objects as values, but it simplifies the problem). The following snippet exemplifies what I am trying to do:
import wx
class ComplexObject(object):
def __init__(self, name, otherdata):
self.name = name
self.otherdata = otherdata
class TestFrame(wx.Frame):
def __init__(self, *args, **kwargs):
super(TestFrame, self).__init__(*args, **kwargs)
self.tree = wx.TreeCtrl(self)
self.rootid = self.tree.AddRoot("Root")
self.tree.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.onrightclick)
self.objectmap = {}
def addobject(self, obj):
itemid = self.tree.AppendItem(self.rootid, obj.name)
self.objectmap[itemid] = obj
def onrightclick(self, event):
itemid = event.GetItem()
if itemid == self.rootid:
return
obj = self.objectmap[itemid]
print "Do something with ComplexObject {}".format(obj.name)
if __name__ == '__main__':
app = wx.App(False)
testframe = TestFrame(None)
for i in range(3):
obj = ComplexObject('obj{}'.format(i), i)
testframe.addobject(obj)
testframe.Show()
app.MainLoop()
When I right-click an entry in the tree I get a KeyError
, because the object I get from the event (itemid = event.GetItem()
) is not the same I get when I add an item (itemid = self.tree.AppendItem(self.rootid, obj.name)
). Is this the expected behavior? How should I proceed to achieve what I am trying to do? I am starting to experiment with SetPyData
and GetPyData
, but I hope there is a better way to do that.
Thank you very much.
Platform Information: MS Windows 7, Python 2.7.9, wxPython 2.8.12.1
Yes, it is expected.
You can think of the TreeItemId
as a closed box with an implementation dependent handle inside, and that the treectrl is the only one that can open the box to get the handle out. You may see different boxes at different times for the same tree item, but they will all have the same handle inside. But since the handle itself is an implementation detail there is no program access to it.
Using SetPyData
to associate data to tree items is the proper way to do things like this. If you want to keep your associated data in a separate dictionary then you could generate unique dictionary keys when adding the items, and then pass they key to SetPyData
, and use GetPyData
to fetch the key later when you need to fetch the value object from the dictionary.