Delphi - 如何将记录添加到现有的treenode

时间:2018-05-17 07:17:29

标签: delphi treeview

我有一个现有的TreeView,其中节点是使用创建的 jQuery( document ).ready(function() { jQuery('.widget > ul').addClass('nav nav-list'); }); (即没有添加数据对象)

我想在每个节点上添加一条记录,以便为每个节点存储一些数据。

有没有办法解决这个问题?

2 个答案:

答案 0 :(得分:4)

定义您自己的类型。这是基于Delphi7帮助。

type
  PItemRecord = ^TItemRecord;
  TItemRecord = record
     Text: string;
  end;

工作示例:

unit FMainTree;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  PItemRecord = ^TItemRecord;
  TItemRecord = record
     Text: string;
  end;

type
  TForm1 = class(TForm)
    tree: TTreeView;
    ButtonAdd: TButton;
    procedure ButtonAddClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ButtonAddClick(Sender: TObject);
var
   i: Integer;
   pdata: PItemRecord;
   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];
      New(pdata);
      pdata^.Text := 'Text for node ' + node.Text;
      node.Data := pdata;
   end{for};
   // Show 'Data' for second item
   ShowMessage(PItemRecord(tree.Items[1].Data)^.Text);
end;

end.

注意:

最好破坏使用New()分配的内存,尽管在程序退出时释放了这个内存。这可以在TreeView的OnDeletion事件中完成:

procedure TForm1.treeDeletion(Sender: TObject; Node: TTreeNode);
begin
   Dispose(PItemRecord(Node.Data));
end;

答案 1 :(得分:0)

虽然Zhorov的回答很好,但如果使用不当可能会导致内存泄漏。

也就是说,如果您使用New分配记录,则必须确保在删除树节点之前释放记录。

我不会使用记录,而是将自定义类的对象分配给节点的Data属性,并使用TObjectList跟踪对象,以确保在表单(或者申请)已关闭。

以下是Zhorov代码的修改版本:

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.
...

当然,使用对象而不是记录会占用更多内存,如果有数千个节点,则可能会影响性能。