2017-04-25 20 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;