如何解决我应该如何为TTreeNodes实现GetLastNode?
| 当我需要在“ 0”中找到第一个节点时,我称“ 1”。但是,有时我需要定位树中的最后一个节点,并且没有相应的“ 2”函数。 我不想使用Items[Count-1]
,因为这样会导致整个树被Result := Result.GetNext
遍历。自然,这仅在树视图具有许多节点的情况下才重要。我完全赞赏虚拟容器控件的优点,但我现在还不会切换到Virtual TreeView。
到目前为止,我提出了以下建议:
function TTreeNodes.GetLastNode: TTreeNode;
var
Node: TTreeNode;
begin
Result := GetFirstNode;
if not Assigned(Result) then begin
exit;
end;
while True do begin
Node := Result.GetNextSibling;
if not Assigned(Node) then begin
Node := Result.GetFirstChild;
if not Assigned(Node) then begin
exit;
end;
end;
Result := Node;
end;
end;
任何人都可以:
发现我的逻辑存在缺陷?
提出改进建议?
编辑1
我不愿意保留自己的节点缓存。直到最近,我一直在这样做,但是发现很难跟踪非常间歇的AV,我认为这一定是由于我的缓存不同步所致。显然,一种解决方案是使我的缓存同步代码正常工作,但是由于您难以理解错误时出现的错误,因此我不喜欢缓存。
解决方法
尽管我不是非退出纯粹主义者,但我认为,如果在没有退出的情况下仍然可行,同时又保持了可读性,则可能会喜欢这种选择。
所以这是完全相同的代码,因为我认为您无法以其他任何方式(更快)到达终端节点,但是没有Exit且稍微紧凑:
function TTreeNodes.GetLastNode: TTreeNode;
var
Node: TTreeNode;
begin
Node := GetFirstNode;
Result := Node;
if Result <> nil then
repeat
Result := Node;
if Node <> nil then
Node := Result.GetNextSibling;
if Node = nil then
Node := Result.GetFirstChild;
until Node = nil;
end;
, 我以前使用的方法是使用OnAddition事件上的List.Add和OnDeletion事件上的List.Remove(OnRemove?)来维护TList。然后,您几乎可以立即访问List.Count-1(或任何您需要的内容)。
后期编辑-我不得不说,尽管这很好,但是我后来长大了,并移到了Virtual Tree View :-)
, 如果我要实施它,那可能是我的初稿。
function TTreeNodes.GetLastNode: TTreeNode;
var
Node: TTreeNode;
function GetLastSibling(aNode : TTreeNode) : TTreeNode;
begin
if not Assigned(aNode) then
EXIT(nil);
repeat
Result := aNode;
aNode := Result.GetNextSibling;
until not Assigned(aNode) ;
end;
begin
Node := GetFirstNode;
if not Assigned(Node) then begin
exit;
end;
repeat
Result := GetLastSibling(Node);
Node := Result.GetFirstChild;
until not Assigned(Node);
end;
我觉得这更具可读性。不过可能会稍微慢一些。
我不确定这种方法是否会比items [Count-1]更快,在某些情况下,它可能会更慢,因为TTreeNodes实际上会缓存通过items属性访问的最后一个节点。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。