The data structure you re requesting is very simple, it s so simple I d recommend using the windows-provided TTreeView
: it allows storing the text and an ID straight into the tree s node with no additional work.
尽管我建议使用更简单的<代码> TTreeView 我要谈谈数据结构问题。 首先,将使用,,而不是records。 在你非常简短的法典中,你以非常不舒服的方式重新组合记录和课程: 当您提供<代码>TRoot记录(由于记录被视为“价值”)时,您不再提供树木的“完整副本”: <代码>TRoot的全文将包含相同的<代码>Kids:TList,作为原文,因为各班次,与记录不同,都是参考资料:你重新处理参考值。
还有一个问题,是生命周期管理: 页: 1 因此,你需要一个其他机制来释放所有物体(Kids:TList
)。 你可以将改为array of Tkid
,但是,在通过mon记录时,你必须小心谨慎,因为如果你最不期望的话,你可能最终将大量记录复制。
我认为,最谨慎的做法是,把数据结构建立在states之上,而不是记录:分类案例(目标)作为参考文件通过,因此,你可以把这些数据推向你们所有希望,而没有任何问题。 您还得到了生活周期的内在管理(destructor)。
基地阶级愿意这样做。 阁下注意到,这可以用作根基或基基,因为根基和基基都分享数据: 两人的姓名和身份证:
TNodeClass = class
public
Name: string;
ID: Integer;
end;
如果这一类别被用作根基,它需要一种储存孩子的办法。 我假设你在德尔菲·2010+上重新发言,因此你具有通用性。 这一类别加上一个清单,即:
type
TNode = class
public
ID: integer;
Name: string;
VTNode: PVirtualNode;
Sub: TObjectList<TNode>;
constructor Create(aName: string = ; anID: integer = 0);
destructor Destroy; override;
end;
constructor TNode.Create(aName:string; anID: Integer);
begin
Name := aName;
ID := anID;
Sub := TObjectList<TNode>.Create;
end;
destructor TNode.Destroy;
begin
Sub.Free;
end;
You might not immediately realize this, but this class alone is enough to implement a multi-level tree! Here s some code to fill up the tree with some data:
Root := TNode.Create;
// Create the Contacts leaf
Root.Sub.Add(TNode.Create( Contacts , -1));
// Add some contacts
Root.Sub[0].Sub.Add(TNode.Create( Abraham , 1));
Root.Sub[0].Sub.Add(TNode.Create( Lincoln , 2));
// Create the "Recent Calls" leaf
Root.Sub.Add(TNode.Create( Recent Calls , -1));
// Add some recent calls
Root.Sub[1].Sub.Add(TNode.Create( +00 (000) 00.00.00 , 3));
Root.Sub[1].Sub.Add(TNode.Create( +00 (001) 12.34.56 , 4));
你们需要一种回收程序,以利用这种类型来填补虚拟树情:
procedure TForm1.AddNodestoTree(ParentNode: PVirtualNode; Node: TNode);
var SubNode: TNode;
ThisNode: PVirtualNode;
begin
ThisNode := VT.AddChild(ParentNode, Node); // This call adds a new TVirtualNode to the VT, and saves "Node" as the payload
Node.VTNode := ThisNode; // Save the PVirtualNode for future reference. This is only an example,
// the same TNode might be registered multiple times in the same VT,
// so it would be associated with multiple PVirtualNode s.
for SubNode in Node.Sub do
AddNodestoTree(ThisNode, SubNode);
end;
// And start processing like this:
VT.NodeDataSize := SizeOf(Pointer); // Make sure we specify the size of the node s payload.
// A variable holding an object reference in Delphi is actually
// a pointer, so the node needs enough space to hold 1 pointer.
AddNodesToTree(nil, Root);
When using objects, different nodes in your Virtual Tree may have different types of objects associated with them. In our example we re only adding nodes of TNode
type, but in the real world you might have nodes of types TContact
, TContactCategory
, TRecentCall
, all in one VT. You ll use the is
operator to check the actual type of the object in the VT node like this:
procedure TForm1.VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var PayloadObject:TObject;
Node: TNode;
Contact : TContact;
ContactCategory : TContactCategory;
begin
PayloadObject := TObject(VT.GetNodeData(Node)^); // Extract the payload of the node as a TObject so
// we can check it s type before proceeding.
if not Assigned(PayloadObject) then
CellText := Bug: Node payload not assigned
else if PayloadObject is TNode then
begin
Node := TNode(PayloadObject); // We know it s a TNode, assign it to the proper var so we can easily work with it
CellText := Node.Name;
end
else if PayloadObject is TContact then
begin
Contact := TContact(PayloadObject);
CellText := Contact.FirstName + + Contact.LastName + ( + Contact.PhoneNumber + ) ;
end
else if PayloadObject is TContactCategory then
begin
ContactCategory := TContactCategory(PayloadObject);
CellText := ContactCategory.CategoryName + ( + IntToStr(ContactCategory.Contacts.Count) + contacts) ;
end
else
CellText := Bug: don t know how to extract CellText from + PayloadObject.ClassName;
end;
这里就是一个例子,说明为什么要把虚拟诺德点放在你的 no子上:
procedure TForm1.ButtonModifyClick(Sender: TObject);
begin
Root.Sub[0].Sub[0].Name := Someone else ; // I ll modify the node itself
VT.InvalidateNode(Root.Sub[0].Sub[0].VTNode); // and invalidate the tree; when displayed again, it will
// show the updated text.
end;
你们知道,在简单的树木数据结构方面有一个工作榜样。 你需要“浏览”这一数据结构,以适应你们的需要:可能性是无限的! 给你一些想法,指示探讨:
- You can turn the
Name:string
into a virtual method GetText:string;virtual
and then create specialized descendants of TNode
that override GetText
to provide specialized behavior.
- Create a
TNode.AddPath(Path:string; ID:Integer)
that allows you to do Root.AddPath( ContactsAbraham , 1);
- that is, a method that automatically creates all intermediary nodes to the final node, to allow easy creation of the tree.
- Include an
PVirtualNode
into TNode
itself so you can check rather the Node is "checked" in the Virtual Tree. This would be a bridge of the data-GUI separation.