Skip to main content

Your First Tree Diagram

Let’s create a simple organizational chart to learn TeeTree basics.
1

Create the Tree Component

// Drop a TTree component on your form from the Component Palette
// Set properties:
Tree1.Align := alClient;
2

Add Your First Nodes

procedure TForm1.CreateOrgChart;
var
  CEO, VP1, VP2: TTreeNodeShape;
begin
  // Add root node (CEO)
  CEO := Tree1.AddRoot('CEO');
  
  // Add child nodes (VPs)
  VP1 := CEO.AddChild('VP Sales');
  VP2 := CEO.AddChild('VP Engineering');
  
  // Add more children
  VP1.AddChild('Sales Manager');
  VP1.AddChild('Marketing Manager');
  
  VP2.AddChild('Dev Team Lead');
  VP2.AddChild('QA Team Lead');
  
  // Expand to show all nodes
  CEO.Expanded := True;
  VP1.Expanded := True;
  VP2.Expanded := True;
end;
3

Run and View

Press F9 to run your application. You should see a hierarchical tree diagram with automatic layout!

Adding Connections

Create visual connections between non-hierarchical nodes:
procedure TForm1.CreateConnectionExample;
var
  NodeA, NodeB, NodeC: TTreeNodeShape;
  Connection: TTreeConnection;
begin
  // Create nodes
  NodeA := Tree1.AddRoot('Process A');
  NodeB := Tree1.AddRoot('Process B');
  NodeC := Tree1.AddRoot('Process C');
  
  // Position nodes
  NodeA.X0 := 50;
  NodeA.Y0 := 50;
  NodeB.X0 := 200;
  NodeB.Y0 := 50;
  NodeC.X0 := 125;
  NodeC.Y0 := 150;
  
  // Create connections
  Connection := NodeA.AddConnection(NodeC);
  Connection.Style := csLine;
  Connection.Border.Color := clBlue;
  
  Connection := NodeB.AddConnection(NodeC);
  Connection.Style := csLine;
  Connection.Border.Color := clRed;
end;

Formatting Nodes

Customize the appearance of individual nodes:
var
  Node: TTreeNodeShape;
begin
  Node := Tree1.AddRoot('Formatted Node');
  
  // Set colors
  Node.Brush.Color := clYellow;
  Node.Font.Color := clBlue;
  
  // Configure border
  Node.Border.Visible := True;
  Node.Border.Color := clRed;
  Node.Border.Width := 2;
end;

Global Formatting

Apply formatting to all new nodes using GlobalFormat:
procedure TForm1.SetupGlobalFormat;
begin
  // Set defaults BEFORE adding nodes
  with Tree1.GlobalFormat do
  begin
    // Hide borders
    Border.Hide;
    
    // Transparent background
    Transparent := True;
    
    // Font settings
    Font.Size := 10;
    Font.Style := [fsBold];
    
    // Connection style
    Connection.ArrowTo.Style := casNone;
  end;
  
  // Now add nodes - they will inherit these settings
  Tree1.AddRoot('Node 1');
  Tree1.AddRoot('Node 2');
end;
Set GlobalFormat properties before adding nodes. Existing nodes are not affected by changes to GlobalFormat.

Working with Text

Nodes support multi-line text:
var
  Node: TTreeNodeShape;
begin
  // Single line - use SimpleText
  Node := Tree1.AddRoot('Hello World');
  Node.SimpleText := 'Updated Text';
end;

Interactive Features

Enable Editing

procedure TForm1.EnableNodeEditing;
begin
  // Allow users to edit node text
  Tree1.AllowEdit := True;
  
  // Or start editing programmatically
  Tree1.StartEditing(Tree1.Roots[0]);
end;

procedure TForm1.Tree1StartEditing(Shape: TTreeNodeShape; 
  var AllowEditing: Boolean);
begin
  // Control which nodes can be edited
  AllowEditing := Shape.Level > 0; // Only children, not roots
end;

Handle Selection

procedure TForm1.Tree1SelectShape(Sender: TTreeNodeShape);
begin
  // Respond to node selection
  ShowMessage('Selected: ' + Sender.SimpleText);
  
  // Access selected nodes
  if Tree1.Selected.Count > 0 then
  begin
    // Get first selected node
    var Node := Tree1.Selected.First;
    Panel1.Caption := Node.SimpleText;
  end;
end;

Mouse Connections

procedure TForm1.ButtonConnectClick(Sender: TObject);
var
  Connection: TTreeConnection;
begin
  // Change cursor
  Tree1.Cursor := crCross;
  Tree1.OriginalCursor := crCross;
  
  // Let user connect two nodes with mouse
  Connection := Tree1.StartConnecting;
  
  // Customize the connection if created
  if Assigned(Connection) then
  begin
    Connection.Style := csLine;
    Connection.Border.Color := clRed;
  end;
  
  // Restore cursor
  Tree1.Cursor := crDefault;
  Tree1.OriginalCursor := crDefault;
end;

Performance with Many Nodes

When adding many nodes, use BeginUpdate and EndUpdate:
procedure TForm1.CreateLargeTree;
var
  i, j: Integer;
  Root, Child: TTreeNodeShape;
begin
  Tree1.BeginUpdate;
  try
    // Add 500 root nodes
    for i := 0 to 499 do
    begin
      Root := Tree1.AddRoot('Node ' + IntToStr(i));
      
      // Add 10 children to each
      for j := 0 to 9 do
      begin
        Child := Root.Add('Child ' + IntToStr(j));
      end;
    end;
  finally
    Tree1.EndUpdate; // Refresh once at the end
  end;
  
  ShowMessage('Added ' + IntToStr(Tree1.Items.Count) + ' nodes');
end;
This approach can add 20,000+ nodes in under 100 milliseconds.

Common Patterns

Iterate Through All Nodes

procedure TForm1.ProcessAllNodes;
var
  i: Integer;
  Node: TTreeNodeShape;
begin
  for i := 0 to Tree1.Items.Count - 1 do
  begin
    Node := Tree1.Items[i];
    // Process node
    Node.Font.Color := clBlue;
  end;
end;

Find a Node

var
  Node: TTreeNodeShape;
begin
  // Find by text
  Node := Tree1.Items.Find('Search Term');
  if Assigned(Node) then
    Node.Selected := True;
    
  // Find by partial text
  Node := Tree1.Items.Find('Partial', True);
end;

Access Node Hierarchy

procedure TForm1.ExploreHierarchy(Node: TTreeNodeShape);
var
  i: Integer;
begin
  // Parent
  if Assigned(Node.Parent) then
    ShowMessage('Parent: ' + Node.Parent.SimpleText);
  
  // Children
  for i := 0 to Node.Count - 1 do
  begin
    ShowMessage('Child: ' + Node.Children[i].SimpleText);
  end;
  
  // Root nodes
  for i := 0 to Tree1.Roots.Count - 1 do
  begin
    ShowMessage('Root: ' + Tree1.Roots[i].SimpleText);
  end;
end;

Delete Nodes

procedure TForm1.DeleteSelectedNodes;
begin
  // Delete all selected nodes
  Tree1.Selected.Clear; // Or delete individually
  
  // Delete specific node (and all children)
  if Assigned(Tree1.Roots[0]) then
    Tree1.Roots[0].Free;
end;

Layout Customization

Change the child layout algorithm:
procedure TForm1.SetupLayout;
var
  Manager: TTreeExplorerAlignChild;
begin
  // Access the child manager
  Manager := Tree1.GlobalFormat.ChildManager as TTreeExplorerAlignChild;
  
  // Adjust spacing
  Manager.HorizMargin := 30;
  Manager.VertMargin := 10;
  
  // Refresh layout
  Tree1.Invalidate;
end;

Zoom and Scroll

procedure TForm1.ConfigureZoom;
begin
  // Enable zoom
  Tree1.Zoom.Allow := True;
  Tree1.Zoom.Pen.Color := clRed;
  
  // Zoom programmatically
  Tree1.Zoom.ZoomPercent := 150; // 150%
  
  // Scroll to node
  Tree1.ScrollToShape(Tree1.Roots[0]);
end;

Save and Load

procedure TForm1.SaveTree;
begin
  if SaveDialog1.Execute then
    Tree1.SaveToFile(SaveDialog1.FileName);
end;

Next Steps

API Reference

Explore all TTree, TTreeNodeShape, and TTreeConnection properties and methods

Advanced Features

Learn about virtual nodes, custom shapes, animations, and more

Database Integration

Use DBTree to automatically generate hierarchies from datasets

Examples

Browse complete example projects and code snippets

Complete Example

Here’s a complete, runnable example:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  TeeTree, TeeProcs;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    Tree1: TTree;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Create tree at runtime
  Tree1 := TTree.Create(Self);
  Tree1.Parent := Self;
  Tree1.Align := alClient;
  
  // Configure appearance
  Tree1.Gradient.Visible := True;
  Tree1.Gradient.StartColor := clWhite;
  Tree1.Gradient.EndColor := clSkyBlue;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  CEO, VP1, VP2: TTreeNodeShape;
begin
  Tree1.BeginUpdate;
  try
    // Create organizational chart
    CEO := Tree1.AddRoot('Chief Executive Officer');
    CEO.Brush.Color := clYellow;
    CEO.Font.Style := [fsBold];
    
    VP1 := CEO.AddChild('VP of Sales');
    VP1.AddChild('Sales Manager');
    VP1.AddChild('Marketing Manager');
    
    VP2 := CEO.AddChild('VP of Engineering');
    VP2.AddChild('Dev Team Lead');
    VP2.AddChild('QA Team Lead');
    
    // Expand all
    CEO.Expanded := True;
    VP1.Expanded := True;
    VP2.Expanded := True;
  finally
    Tree1.EndUpdate;
  end;
end;

end.
This example creates a fully functional organizational chart with formatted nodes and automatic hierarchical layout.

Build docs developers (and LLMs) love