Delphi – How to remove nodes from TTREEVIEW and its objects

I am using Delphi 10 Starter version. I am studying how to use Delphi’s TTreeView component.

Everything is normal, no problem. The only thing I left The question is:

After adding the object to the node, what is the correct way to delete the item and its object?

This is my code (see Button6Click):

type
TMyNode2 = class
public
nom: Integer;
comm: String;
end;

var
Form1: TForm1;
MyNode2: TMyNode2;

procedure TForm1.Button1Click(Sender: TObject); // add node
var
x: TTreeNode;
begin
x := tv1.Items.Add(tv1.Selected, Edit1. Text + '' + IntToStr(Round(Random(100))));
x.ImageIndex := 1;
x.SelectedIndex := x.ImageIndex;
x.StateIndex := x.ImageIndex;
end;

procedure TForm1.Button4Click(Sender: TObject); // add child node
var
x: TTreeNode;
begin
x := tv1.Items.AddChild(tv1.Selected,'Child '+ Edit1.Text +' '+ IntToStr(Round(Random(100))));
x.ImageIndex := 2;
x.SelectedIndex := x.ImageIndex;
x.StateIndex := x.ImageIndex;
tv1.Selected.Expand(true);
x.Selected := true;
x.Expand(true);
end;

procedure TForm1.Button2Click(Sender: TObject); // del node (if not 1st)
var
x, y: TTreeNode;
begin
y := tv1.Items[0];
x := tv1.Selected;
if x <> y then
x.Delete
else
ShowMessage('Do not del 1st node!');
end ;

procedure TForm1.Button3Click(Sender: TObject); // add node (v.2 as object)
var
x: TTreeNode;
begin
MyNode2 := TMyNode2.Create;
MyNode2.nom := Round(Random(1000));
MyNode2.comm := IntToStr(MyNode2.nom) + 'comment' + IntToStr(MyNode2. nom);
x := tv1.Items.AddObject(tv1.Selected, Edit1.Text + '' + IntToStr(Round(Random(1000))), Pointer(MyNode2));
x. ImageIndex := 3;
x.SelectedIndex := x.ImageIndex;
x.StateIndex := x.ImageIndex;
tv1.Selected.Expand(true);
x. Selected := true;
x.Expand(true);
end;

procedure TForm1.Button5Click(Sender: TObject); // add child node (v.2 as object)
var
x: TTreeNode;
begin
MyNode2 := TMyNo de2.Create;
MyNode2.nom := Round(Random(1000));
MyNode2.comm := IntToStr(MyNode2.nom) + 'child comment' + IntToStr(MyNode2.nom);< br /> x := tv1.Items.AddChildObject(tv1.Selected, Edit1.Text + '' + IntToStr(Round(Random(1000))), Pointer(MyNode2));
x.ImageIndex := 4 ;
x.SelectedIndex := x.ImageIndex;
x.StateIndex := x.ImageIndex;
tv1.Selected.Expand(true);
x.Selected := true ;
x.Expand(true);
end;

procedure TForm1.Button6Click(Sender: TObject); // del node (if not 1st) and "as" object
var
x, y: TTreeNode;
begin
y := tv1.Items[0];
x := tv1.Selected;
if x <> y then begin
//class(x.tMyNode2(node.Data)).Free; // **** // !!!!!!!!!!!!!!!< br /> x.Delete;
end else
ShowMessage('Do not del 1st node!');
end;

procedure TForm1.FormCreate(Sender: TObject); // on create-add data 2 1st node
var
x: TTreeNode;
begin
MyNode2 := TMyNode2.Create;
MyNode2.nom := 100001;
MyNode2.comm := '1st node comment';
x := tv1.Items[0];
x. Data := Pointer(MyNode2);
end;

procedure TForm1.tv1Change(Sender: TObject; Node: TTreeNode); // look node prop.
begin
if Node = nil then
Caption:='Not select'
else
if Node.Data = nil then
Caption := Format('Nom: %d, Im. Ind: %d', [Integer(Node.Index), Integer(Node.ImageIndex)])
else
Caption := Format('Nom: %d, Im.Ind: %d, MyNode .Nom: %d, Comm: %s', [Integer(Node.Index), Integer(Node.ImageIndex), Integer(TMyNode2(node.Data).nom), string(TMyNode2(node.Data).comm) ]);
end;

Use TreeView’s OnDeletion event, which is Triggered when TTreeNode is deleted in

procedure TForm1.tv1Deletion(Sender: TObject; Node: TTreeNode);
begin
TMyNode2(Node. Data).Free;
// or simply:
// TObject(Node.Data).Free;
end;

Therefore:

procedure TForm1.Button2Click(Sender: TObject);
// del node (if not 1st)
var
x, y: TTreeNode;
begin
x := tv1.Selected;
if x <> nil then
begin
y := tv1.Items.GetFirstNode ;
if x <> y then
x.Delete
else
ShowMessage('Do not del 1st node!');
end;
end ;

procedure TForm1.Button6Click(Sender: TObject);
// del node (if not 1st) and its object
var
x, y: TTreeNode;
begin
x := tv1.Selected;
if x <> nil then
begin
y := tv1.Items.GetFirstNode;
if x <> y then
x.Delete
else
ShowMessage('Do not del 1st node!');
end;
end;

As you can see, Button2Click() and Button6Click() are now exactly the same, so you can delete one of them. Unless you really want Button2Click() not to release the node’s object, in this case you can call x.Delete () Set x.Data to nil before (you are still responsible for tracking the object so that you can release it later, otherwise it will be leaked):

procedure TForm1.Button2Click( Sender: TObject);
// del node (if not 1st) but not its object
var
x, y: TTreeNode;
begin
x := tv1.Selected;
if x <> nil then
begin
y := tv1.Items.GetFirstNode;
if x <> y then
begin
x.Data := nil; // <--! !!
x.Delete;
end else
ShowMessage('Do not del 1st node!');
end;
end;

procedure TForm1.Button6Click(Sender: TObject);
// del node (if not 1st) and its object
var
x, y: TTreeNode;
begin
x := tv1.Selected;
if x <> nil then
begin
y := tv1.Items.GetFirstNode;
if x <> y then
x.Delete
else
ShowMessage('Do not del 1st node!');
end;
end;

< p>I’m using Delphi 10 Starter version. I’m studying how to use Delphi’s TTreeView component.

Everything is normal and there is no problem. The only question I left is:

After adding the object to the node, what is the correct way to delete the item and its object?

This is my code (see Button6Click):

type
TMyNode2 = class
public
nom: Integer;
comm: String;
end;

var
Form1: TForm1;
MyNode2: TMyNode2;

procedure TForm1.Button1Click(Sender: TObject); // add node
var
x: TTreeNode;
begin
x := tv1.Items.Add(tv1.Selected, Edit1. Text + '' + IntToStr(Round(Random(100))));
x.ImageIndex := 1;
x.SelectedIndex := x.ImageIndex;
x.StateIndex := x.ImageIndex;
end;

procedure TForm1.Button4Click(Sender: TObject); // add child node
var
x: TTreeNode;
begin
x := tv1.Items.AddChild(tv1.Selected,'Child '+ Edit1.Text +' '+ IntToStr(Round(Random(100))));
x.ImageIndex := 2;
x.SelectedIndex := x.ImageIndex;
x.StateIndex := x.ImageIndex;
tv1.Selected.Expand(true);
x.Selected := true;
x.Expand(true);
end;

procedure TForm1.Button2Click(Sender: TO bject); // del node (if not 1st)
var
x, y: TTreeNode;
begin
y := tv1.Items[0];
x := tv1.Selected;
if x <> y then
x.Delete
else
ShowMessage('Do not del 1st node!');
end ;

procedure TForm1.Button3Click(Sender: TObject); // add node (v.2 as object)
var
x: TTreeNode;
begin
MyNode2 := TMyNode2.Create;
MyNode2.nom := Round(Random(1000));
MyNode2.comm := IntToStr(MyNode2.nom) + 'comment' + IntToStr(MyNode2. nom);
x := tv1.Items.AddObject(tv1.Selected, Edit1.Text + '' + IntToStr(Round(Random(1000))), Pointer(MyNode2));
x. ImageIndex := 3;
x.SelectedIndex := x.ImageIndex;
x.StateIndex := x.ImageIndex;
tv1.Selected.Expand(true);
x. Selected := true;
x.Expand(true);
end;

procedure TForm1.Button5Click(Sender: TObject); // add child node (v.2 as object)
var
x: TTreeNode;
begin
MyNode2 := TMyNode2 .Create;
MyNode2.nom := Round(Random(1000));
MyNode2.comm := IntToStr(MyNode2.nom) + 'child comment' + IntToStr(MyNode2.nom);
x := tv1.Items.AddChildObject(tv1.Selected, Edit1.Text + '' + IntToStr(Round(Random(1000))), Pointer(MyNode2));
x.ImageIndex := 4;
x.SelectedIndex := x.ImageIndex;
x.StateIndex := x.ImageIndex;
tv1.Selected.Expand(true);
x.Selected := true;
x.Expand(true);
end;

procedure TForm1.Button6Click(Sender: TObject); // del node (if not 1st) and "as" object< br />var
x, y: TTreeNode;
begin
y := tv1.Items[0];
x := tv1.Selected;
if x <> y then begin
//class(x.tMyNode2(node.Data)).Free; // **** // !!!!!!!!!!!!!!!
x.Delete;
end else
ShowMessage('Do not del 1st node!');
end;

procedure TForm1.FormCreate(Sender: TObject ); // on create-add data 2 1st node
var
x: TTreeNode;
begin
MyNode2 := TM yNode2.Create;
MyNode2.nom := 100001;
MyNode2.comm := '1st node comment';
x := tv1.Items[0];
x. Data := Pointer(MyNode2);
end;

procedure TForm1.tv1Change(Sender: TObject; Node: TTreeNode); // look node prop.
begin
if Node = nil then
Caption:='Not select'
else
if Node.Data = nil then
Caption := Format('Nom: %d, Im. Ind: %d', [Integer(Node.Index), Integer(Node.ImageIndex)])
else
Caption := Format('Nom: %d, Im.Ind: %d, MyNode .Nom: %d, Comm: %s', [Integer(Node.Index), Integer(Node.ImageIndex), Integer(TMyNode2(node.Data).nom), string(TMyNode2(node.Data).comm) ]);
end;

Use TreeView’s OnDeletion event, which is triggered when TTreeNode is deleted from the tree:

procedure TForm1.tv1Deletion(Sender: TObject; Node: TTreeNode);
begin
TMyNode2(Node.Data).Free;
// or simply:
// TObject(Node.Data).Free;
end;

Thus:

procedure TForm1.Button2Click (Se nder: TObject);
// del node (if not 1st)
var
x, y: TTreeNode;
begin
x := tv1.Selected;< br /> if x <> nil then
begin
y := tv1.Items.GetFirstNode;
if x <> y then
x.Delete
else< br /> ShowMessage('Do not del 1st node!');
end;
end;

procedure TForm1.Button6Click(Sender: TObject);
/ / del node (if not 1st) and its object
var
x, y: TTreeNode;
begin
x := tv1.Selected;
if x <> nil then
begin
y := tv1.Items.GetFirstNode;
if x <> y then
x.Delete
else
ShowMessage('Do not del 1st node!');
end;
end;

As you can see, Button2Click() and Button6Click() are now exactly the same, so you can delete one of them. Unless you really want Button2Click() not to release the object of the node, in this case you can set x.Data to nil before calling x.Delete() (you are still responsible for tracking the object so that you can release it later, Otherwise it will be leaked):

procedure TForm1.Button2Click(Sender: TObject);
// del node (if not 1st) but not its object
var
x, y: TTreeNo de;
begin
x := tv1.Selected;
if x <> nil then
begin
y := tv1.Items.GetFirstNode;
if x <> y then
begin
x.Data := nil; // <-- !!!
x.Delete;
end else
ShowMessage( 'Do not del 1st node!');
end;
end;

procedure TForm1.Button6Click(Sender: TObject);
// del node (if not 1st) and its object
var
x, y: TTreeNode;
begin
x := tv1.Selected;
if x <> nil then
begin
y := tv1.Items.GetFirstNode;
if x <> y then
x.Delete
else
ShowMessage('Do not del 1st node! ');
end;
end;

Leave a Comment

Your email address will not be published.