TreeView Demo

live scene tree inspector with expand/collapse.

▶ Run in browser

Tags: ui

Displays a simulated scene hierarchy in a TreeView widget. Users can expand/collapse branches, select items, add children to the selected node, or remove the selected node. A status label reflects the current selection.

Run: uv run python examples/features/ui/tree.py

Source

  1"""TreeView Demo -- live scene tree inspector with expand/collapse.
  2
  3Displays a simulated scene hierarchy in a TreeView widget. Users can
  4expand/collapse branches, select items, add children to the selected
  5node, or remove the selected node. A status label reflects the
  6current selection.
  7
  8Run: uv run python examples/features/ui/tree.py
  9"""
 10
 11from simvx.core import (
 12    AnchorPreset,
 13    Button,
 14    Colour,
 15    HBoxContainer,
 16    Label,
 17    Node,
 18    Panel,
 19    TreeItem,
 20    TreeView,
 21    VBoxContainer,
 22    Vec2,
 23)
 24from simvx.graphics import App
 25
 26
 27class TreeDemo(Node):
 28    """Root node for the tree view demo scene."""
 29
 30    _node_counter = 0
 31
 32    def on_ready(self):
 33        # --- Background panel ---
 34        panel = Panel(name="MainPanel")
 35        # Fill the viewport with a comfortable gutter so the tree grows on resize.
 36        panel.set_anchor_preset(AnchorPreset.FULL_RECT)
 37        panel.margin_left = 30
 38        panel.margin_top = 20
 39        panel.margin_right = 30
 40        panel.margin_bottom = 20
 41        panel.bg_colour = Colour.hex("#1A1A2E")
 42        panel.border_colour = Colour.hex("#16213E")
 43        self.add_child(panel)
 44
 45        vbox = VBoxContainer(name="Layout")
 46        vbox.set_anchor_preset(AnchorPreset.FULL_RECT)
 47        vbox.margin_left = 10
 48        vbox.margin_top = 10
 49        vbox.margin_right = 10
 50        vbox.margin_bottom = 10
 51        vbox.separation = 10
 52        panel.add_child(vbox)
 53
 54        # --- Title ---
 55        title = Label("Scene Tree Inspector")
 56        title.text_colour = Colour.hex("#E94560")
 57        title.font_size = 18.0
 58        title.size = Vec2(400, 28)
 59        title.alignment = "center"
 60        vbox.add_child(title)
 61
 62        # --- Build scene hierarchy ---
 63        root_item = TreeItem("Root")
 64
 65        world = root_item.add_child(TreeItem("World"))
 66        world.add_child(TreeItem("Player (Node3D)"))
 67        world.add_child(TreeItem("Enemy1 (Node3D)"))
 68        world.add_child(TreeItem("Enemy2 (Node3D)"))
 69
 70        ui_branch = root_item.add_child(TreeItem("UI"))
 71        ui_branch.add_child(TreeItem("HUD"))
 72        ui_branch.add_child(TreeItem("Menu"))
 73
 74        root_item.add_child(TreeItem("Camera"))
 75
 76        # --- TreeView widget ---
 77        tree = TreeView(root=root_item, name="SceneTree")
 78        tree.size = Vec2(400, 300)
 79        tree.bg_colour = Colour.hex("#0A0A1A")
 80        tree.select_colour = Colour.hex("#0F3460")
 81        tree.text_colour = Colour.LIGHT_GRAY
 82        vbox.add_child(tree)
 83
 84        # --- Status label ---
 85        status = Label("Selected: (none)")
 86        status.text_colour = Colour.CYAN
 87        status.size = Vec2(400, 22)
 88        vbox.add_child(status)
 89
 90        def on_select(item):
 91            status.text = f"Selected: {item.text}"
 92
 93        tree.item_selected.connect(on_select)
 94
 95        # --- Action buttons ---
 96        btn_row = HBoxContainer(name="Actions")
 97        btn_row.size = Vec2(400, 35)
 98        btn_row.separation = 10
 99        vbox.add_child(btn_row)
100
101        def add_node():
102            parent = tree.selected or root_item
103            TreeDemo._node_counter += 1
104            parent.add_child(TreeItem(f"NewNode{TreeDemo._node_counter}"))
105            parent.expanded = True
106
107        def remove_selected():
108            sel = tree.selected
109            if sel and sel is not root_item and sel.parent:
110                sel.parent.remove_child(sel)
111                tree.selected = None
112                status.text = "Selected: (none)"
113
114        add_btn = Button("Add Node", on_press=add_node)
115        add_btn.size = Vec2(120, 35)
116        add_btn.bg_colour = Colour.hex("#0F3460")
117        add_btn.hover_colour = Colour.hex("#1A4A7A")
118        btn_row.add_child(add_btn)
119
120        rm_btn = Button("Remove Selected", on_press=remove_selected)
121        rm_btn.size = Vec2(160, 35)
122        rm_btn.bg_colour = Colour.hex("#533483")
123        rm_btn.hover_colour = Colour.hex("#6A4599")
124        btn_row.add_child(rm_btn)
125
126
127if __name__ == "__main__":
128    app = App(title="SimVX Tree Demo", width=800, height=600)
129    app.run(TreeDemo())