2017-04-25 95 views
3

我正在使用Delphi 10 Starter版本。我正在研究如何使用Delphi的TTreeView组件。如何从TTreeView中删除节点及其对象

一切正常,没有问题。我留下的唯一问题是:

将对象添加到节点后,删除项目及其对象的正确方法是什么?

这里是我的代码(见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; 

回答

7

使用TreeView的OnDeletion事件,当TTreeNode正在从树中移除时被触发:

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

这样:

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; 

正如你所看到的,Button2Click()Button6Click()现在完全相同,因此您可以删除其中的一个。除非你真的想要Button2Click()不释放节点的对象,在这种情况下,你可以在调用x.Delete()之前设置x.Datanil(你仍然负责跟踪对象的某处,以便稍后释放它,否则它将被泄露):

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;