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;
uses
TeeTree;
var
Tree1: TTree;
begin
Tree1 := TTree.Create(Self);
Tree1.Parent := Self;
Tree1.Align := alClient;
end;
uses
FMXTee.Tree, FMXTee.Procs;
var
Tree1: TTree;
begin
Tree1 := TTree.Create(Self);
Tree1.Parent := Self;
Tree1.BoundsRect := RectF(0, 0, 400, 600);
end;
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;
var
Node: TTreeNodeShape;
begin
Node := Tree1.AddRoot('Gradient Node');
// Enable gradient
Node.Gradient.Visible := True;
Node.Gradient.StartColor := clWhite;
Node.Gradient.EndColor := clSkyBlue;
Node.Gradient.Direction := gdTopBottom;
// Add shadow
Node.Shadow.Visible := True;
Node.Shadow.Size := 5;
end;
var
Node: TTreeNodeShape;
begin
Node := Tree1.AddRoot('Custom Shape');
// Set shape style
Node.Shape.Style := tsRoundRectangle;
// Add icon
Node.ImageIndex := tiFolderOpenClose;
// Adjust size
Node.Width := 120;
Node.Height := 60;
end;
Global Formatting
Apply formatting to all new nodes usingGlobalFormat:
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;
var
Node: TTreeNodeShape;
begin
Node := Tree1.AddRoot('');
// Add multiple lines
Node.Text.Clear;
Node.Text.Add('Line 1');
Node.Text.Add('Line 2');
Node.Text.Add('Line 3');
// Text alignment
Node.Text.HorizAlign := htaLeft;
Node.Text.VertAlign := vtaTop;
end;
var
Node: TTreeNodeShape;
begin
Node := Tree1.AddRoot('');
// Copy from TMemo
Node.Text.Assign(Memo1.Lines);
// Text angle (rotation)
Node.Text.Angle := 45; // degrees
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, useBeginUpdate 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;
procedure TForm1.LoadTree;
begin
if OpenDialog1.Execute then
begin
Tree1.Clear; // Remove existing nodes
Tree1.LoadFromFile(OpenDialog1.FileName);
end;
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.
