Search code examples
pythonpython-2.7wxpythontreecontrol

wxPython TreeCtrl: Get an treeitem's data by index


How do I get a tree item's data by index of the tree?

I'm currently writing a GUI with wxPython (using Python 2.7). This GUI contains a CustomTreeCtrl that is build as follows:

    # Create Tree control
    widget_tree = CustomTreeCtrl(parent=self, id=ID_WIDGET_TREE, agwStyle=wx.TR_HIDE_ROOT | wx.TR_SINGLE | wx.TR_HAS_BUTTONS, 
                                 size=(UI_tree_width, -1))
    widget_tree.SetBackgroundColour(wx.WHITE)
    root = widget_tree.AddRoot(text="root")

# Create general
    item_general = widget_tree.AppendItem(parentId=root, text='General')
    item_main = widget_tree.AppendItem(parentId=item_general, text='Main', data={'tooltip': 'Main'})
    widget_tree.AppendItem(parentId=item_general, text='Manual', data={'tooltip': 'Manual'})
    widget_tree.AppendItem(parentId=item_general, text='Boundary conditions', data={'tooltip': 'BC'})

    # Create stiffeners
    item_stiffener = widget_tree.AppendItem(parentId=root, text='Stiffeners')
    widget_tree.AppendItem(parentId=item_stiffener, text='Stiffener 1', data={'tooltip': 'Stiffener 1'})
    widget_tree.AppendItem(parentId=item_stiffener, text='Stiffener 2', data={'tooltip': 'Stiffener 2'})
    widget_tree.AppendItem(parentId=item_stiffener, text='Add stiffener', data={'tooltip': 'Creates a new stiffener'})

The data will be extended with certain input by the user. Besides that clicking on 'Add stiffener' will insert an item above 'Add stiffener'. For the purpose of the tool I need to get this data from every stiffener. I was wondering if it is possible to call these like lists in lists. So for example I could call widget_tree.GetTreeItem[0][1][0] for [root][stiffeners][stiffener 1] and so on.

I've been looking for a while now and was hoping someone could help me out. Thanks in advance!


Solution

  • I inherited a project that had a massively complicated way to do what you're asking for, but your post gave me a new idea. Conceptually, I think you're talking about something similar to the get_item_by_indexes method in this example (I left in all the debug prints):

    import wx
    from wx.lib.agw.customtreectrl import CustomTreeCtrl
    
    class IndexTree(CustomTreeCtrl):
    def get_item_by_indexes(self, *args):
        args = list(args)  # copy so we don't modify original
        print("Trying tree index: %s" % str(args))
        if args[0] > 0:
            raise IndexError("Invalid root index")
        parent = self.GetRootItem()
        print("arg_index=0, tree_index=0, item=%s" % (parent.GetText()))
        for arg_index, tree_index in enumerate(args[1:], 1):
            parent = parent.GetChildren()[tree_index]
            print("arg_index=%d, tree_index=%d, item=%s" % (arg_index, tree_index, parent.GetText()))
        return parent
    
    class MyFrame(wx.Frame):
        def __init__(self, parent, id, title):
            wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.DefaultSize)
            widget_tree = IndexTree(parent=self, agwStyle=wx.TR_HIDE_ROOT | wx.TR_SINGLE | wx.TR_HAS_BUTTONS, 
                                     size=(400, -1))
            widget_tree.SetBackgroundColour(wx.WHITE)
            root = widget_tree.AddRoot(text="root")
    
        # Create general
            item_general = widget_tree.AppendItem(parentId=root, text='General')
            item_main = widget_tree.AppendItem(parentId=item_general, text='Main', data={'tooltip': 'Main'})
            widget_tree.AppendItem(parentId=item_general, text='Manual', data={'tooltip': 'Manual'})
            widget_tree.AppendItem(parentId=item_general, text='Boundary conditions', data={'tooltip': 'BC'})
    
            # Create stiffeners
            item_stiffener = widget_tree.AppendItem(parentId=root, text='Stiffeners')
            widget_tree.AppendItem(parentId=item_stiffener, text='Stiffener 1', data={'tooltip': 'Stiffener 1'})
            widget_tree.AppendItem(parentId=item_stiffener, text='Stiffener 2', data={'tooltip': 'Stiffener 2'})
            widget_tree.AppendItem(parentId=item_stiffener, text='Add stiffener', data={'tooltip': 'Creates a new stiffener'})
    
            widget_tree.get_item_by_indexes(0)
            widget_tree.get_item_by_indexes(0, 1)
            widget_tree.get_item_by_indexes(0, 0, 0)
            widget_tree.get_item_by_indexes(0, 1, 0)
            widget_tree.get_item_by_indexes(0, 1, 2)
            try:
                widget_tree.get_item_by_indexes(0, 1, 8)
            except IndexError, e:
                print(e)
    
    class MyApp(wx.App):
        def OnInit(self):
            frame = MyFrame(None, -1, 'IndexTree')
            frame.Show(True)
            frame.Centre()
            return True
    
    if __name__ == '__main__':
        app = MyApp(0)
        app.MainLoop()
    

    which for the test cases produces:

    Trying tree index: [0]
    arg_index=0, tree_index=0, item=root
    Trying tree index: [0, 1]
    arg_index=0, tree_index=0, item=root
    arg_index=1, tree_index=1, item=Stiffeners
    Trying tree index: [0, 0, 0]
    arg_index=0, tree_index=0, item=root
    arg_index=1, tree_index=0, item=General
    arg_index=2, tree_index=0, item=Main
    Trying tree index: [0, 1, 0]
    arg_index=0, tree_index=0, item=root
    arg_index=1, tree_index=1, item=Stiffeners
    arg_index=2, tree_index=0, item=Stiffener 1
    Trying tree index: [0, 1, 2]
    arg_index=0, tree_index=0, item=root
    arg_index=1, tree_index=1, item=Stiffeners
    arg_index=2, tree_index=2, item=Add stiffener
    Trying tree index: [0, 1, 8]
    arg_index=0, tree_index=0, item=root
    arg_index=1, tree_index=1, item=Stiffeners
    list index out of range
    

    A big ol' caveat that I haven't used this in practice yet because I didn't have the idea before seeing your post just now. But I hacked this together and I am interested to see if I can replace my project's overly complicated method.