I am using Delphi 10 Starter edition. I am studying how to use Delphi's TTreeView
component.
Everything works, no issues. The only question I have left is:
After adding an object to a node, what is the right way to delete the item and its object?
Here 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 := 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
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 := 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 the TreeView's OnDeletion
event, which is triggered when a TTreeNode
is being removed 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(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 identical, so you can remove one of them. Unless you really want Button2Click()
to not free the node's object, in which case you can just set x.Data
to nil
before calling x.Delete()
(you are still responsible for keeping track of the object somewhere so you can free it later, or else 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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With