从 TreeEvent 获取的 TreeItemId 与从 AppendItem 获取的不同

TreeItemId obtained from TreeEvent is not the same as obtained from AppendItem

我正在构建一个程序来存储一些复杂的对象,我正在为 UI 使用 wxPython。对象层次结构将具有树形表示 (TreeCtrl)。我正在使用字典将对象从 UI 映射到数据库,使用 AppendItem 返回的 TreeItemId 作为键,对象本身作为值(实际上我没有使用对象作为值,但它简化了问题)。以下片段举例说明了我正在尝试做的事情:

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()

当我右键单击树中的一个条目时,我得到一个 KeyError,因为我从事件 (itemid = event.GetItem()) 中得到的对象与我添加一个项目时得到的对象不同(itemid = self.tree.AppendItem(self.rootid, obj.name))。这是预期的行为吗?我应该如何着手实现我想要做的事情?我开始尝试 SetPyDataGetPyData,但我希望有更好的方法。

非常感谢。

平台信息: MS Windows 7, Python 2.7.9, wxPython 2.8.12.1

是的,这是意料之中的。

你可以把 TreeItemId 想象成一个封闭的盒子,里面有一个依赖于实现的句柄,而 treectrl 是唯一可以打开盒子取出句柄的。对于同一个树项目,您可能会在不同时间看到不同的盒子,但它们内部的手柄都是相同的。但是由于句柄本身是一个实现细节,所以没有程序可以访问它。

使用 SetPyData 将数据关联到树项是执行此类操作的正确方法。如果您想将相关数据保存在单独的字典中,那么您可以在添加项目时生成唯一的字典键,然后将它们的键传递给 SetPyData,并在稍后使用 GetPyData 获取键需要从字典中获取值对象。