Хотя ответ Жорова работает просто отлично, он может привести к утечке памяти при неправильном использовании.
То есть, если вы выделяете запись с New
, вы должны убедиться, что запись будет освобождена до того, какудаление узла дерева.
Вместо использования записей я бы назначил объекты пользовательского класса свойству Data узла и отслеживал объекты с помощью TObjectList
, чтобы сделатьубедитесь, что они правильно уничтожены, когда форма (или приложение) закрыта.
Вот модифицированная версия кода Жорова:
unit FMainTree;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, Contnrs;
type
TMyItem = class
private
FText: string;
public
property Text: string read FText write FText;
end;
TForm1 = class(TForm)
tree: TTreeView;
ButtonAdd: TButton;
procedure ButtonAddClick(Sender: TObject);
private
FItemList: TObjectList;
public
procedure AfterConstruction();
procedure BeforeDestruction();
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure AfterConstruction();
begin
inherited;
// `True` = automatically destroy items when deleted from the list or the list is destroyed
FItemList := TObjectList.Create(True);
end;
procedure BeforeDestruction();
begin
// Destroying the list will also destroy the object items inside
FItemList.Free;
inherited;
end;
procedure TForm1.ButtonAddClick(Sender: TObject);
var
i: Integer;
objData: TMyItem;
node: TTreeNode;
begin
// Add nodes without 'Data'
tree.Items.Add(nil, 'Item1');
tree.Items.Add(nil, 'Item2');
tree.Items.Add(nil, 'Item3');
// Add 'Data'
for i := 0 to tree.Items.Count-1 do begin
node := tree.Items[i];
objData := TMyItem.Create();
try
objData.Text := 'Text for node ' + node.Text;
finally
FItemList.Add(objData);
end;
node.Data := objData;
end{for};
// Show 'Data' for second item
ShowMessage(TMyItem(tree.Items[1].Data).Text);
end;
end.
Я намеренно использовал неуниверсальныйверсия TObjectList (из модуля Contnrs), так как вы не указали версию Delphi, которая у вас есть, поэтому она может не иметь обобщений.Но если у вас Delphi 2009 или новее, обратитесь к следующей статье за примерами того, как использовать это вместо: Generics Collections TObjectList (Delphi) :
...
var
List: TObjectList<TNewObject>;
Obj: TNewObject;
begin
{ Create a new List. }
{ The OwnsObjects property is set by default to true -- the list will free the owned objects automatically. }
List := TObjectList<TNewObject>.Create();
{ Add some items to the List. }
List.Add(TNewObject.Create('One'));
List.Add(TNewObject.Create('Two'));
...
List.Free;
end.
...
Конечно, использование объектов вместо записей потребляет больше памяти, и если у вас есть тысячи узлов, это может повлиять на производительность.