How to remove node and its object from TTreeView

I am using Delphi 10 Starter edition. I am learning how to use a Delphi component TTreeView

.

Everything works, no problem. The only question remains:

After adding an object to a node, what's the way to remove the element 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;

      

+3


source to share


1 answer


Use the TreeView event OnDeletion

that fires when TTreeNode

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 are Button6Click()

now identical, so you can delete one of them. If you really don't want to Button2Click()

not free the node object, in which case you can simply set x.Data

in nil

before the call x.Delete()

(you are still responsible for keeping track of the object somewhere so you can free it later, otherwise it will leak):

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;

      

+7


source







All Articles