gpt4 book ai didi

delphi - Firemonkey和Delphi XE3下如何顺序浏览TTreeView的所有节点?

转载 作者:行者123 更新时间:2023-12-03 15:46:41 24 4
gpt4 key购买 nike

出于性能原因,我需要浏览 TreeView 的项目,而不使用递归。

TTreeview提供GlobalCount和ItemByGlobalIndex方法,但它只返回可见
我搜索了根类代码,没有找到所有节点的私有(private)列表,FGlobalItems似乎只保存需要渲染的项目

有没有办法顺序浏览 TreeView 的所有项目(包括不可见和折叠的节点)?

此问题适用于Delphi XE3/FM2

谢谢

[2 月 3 日编辑]
我接受了默认答案(不可能开箱即用),尽管我正在寻找一种方法来修补这方面的 firemonkey TreeView 。
经过更多分析,我发现 FGlobalItems 列表仅包含扩展项,并在方法 TCustomTreeView.UpdateGlobalIndexes 中维护;
注释 FMX.TreeView 的第 924 行(如果 AItem.IsExpanded 那么...)会导致构建节点的完整索引,并允许使用 ItemByGlobalIndex() 顺序浏览所有节点,但可能会导致其他性能问题和错误...
没有更多线索,我将保留我的递归代码。

最佳答案

以下是我以非递归方式遍历 TreeView 的函数。如果您有一个节点并且想要移动到下一个或上一个节点而不必遍历整个树,那么使用起来很简单。

GetNextItem 的功能是查看它的第一个子项,或者如果没有子项,则查看其父项以查找其自身之后的下一个子项(并根据需要进一步遍历父项)。

GetPrevItem 查看父项以查找前一项,并使用 GetLastChild 查找该项的最后一个子项(顺便说一句,它确实使用了递归)。

请注意,编写的代码仅遍历扩展节点,但可以轻松修改为遍历所有节点(只需删除对 IsExpanded 的引用)。

function GetLastChild(Item: TTreeViewItem): TTreeViewItem;
begin
if (Item.IsExpanded) and (Item.Count > 0) then
Result := GetLastChild(Item.Items[Item.Count-1])
else
Result := Item;
end;

function GetNextItem(Item: TTreeViewItem): TTreeViewItem;
var ItemParent: TTreeViewItem;
I: Integer;
TreeViewParent: TTreeView;
Parent: TFMXObject;
Child: TFMXObject;
begin
if Item = nil then
Result := nil
else if (Item.IsExpanded) and (Item.Count > 0) then
Result := Item.Items[0]
else
begin
Parent := Item.Parent;
Child := Item;
while (Parent <> nil) and not (Parent is TTreeView) do
begin
while (Parent <> nil) and not (Parent is TTreeView) and not (Parent is TTreeViewItem) do
Parent := Parent.Parent;

if (Parent <> nil) and (Parent is TTreeViewItem) then
begin
ItemParent := TTreeViewItem(Parent);
I := 0;
while (I < ItemParent.Count) and (ItemParent.Items[I] <> Child) do
inc(I);
inc(I);
if I < ItemParent.Count then
begin
Result := ItemParent.Items[I];
EXIT;
end;
Child := Parent;
Parent := Parent.Parent
end;
end;

if (Parent <> nil) and (Parent is TTreeView) then
begin
TreeViewParent := TTreeView(Parent);
I := 0;
while (I < TreeViewParent.Count) and (TreeViewParent.Items[I] <> Item) do
inc(I);
inc(I);
if I < TreeViewParent.Count then
Result := TreeViewParent.Items[I]
else
begin
Result := Item;
EXIT;
end;
end
else
Result := Item
end
end;

function GetPrevItem(Item: TTreeViewItem): TTreeViewItem;
var Parent: TFMXObject;
ItemParent: TTreeViewItem;
TreeViewParent: TTreeView;
I: Integer;
begin
if Item = nil then
Result := nil
else
begin
Parent := Item.Parent;
while (Parent <> nil) and not (Parent is TTreeViewItem) and not (Parent is TTreeView) do
Parent := Parent.Parent;

if (Parent <> nil) and (Parent is TTreeViewItem) then
begin
ItemParent := TTreeViewItem(Parent);
I := 0;
while (I < ItemParent.Count) and (ItemParent.Items[I] <> Item) do
inc(I);
dec(I);
if I >= 0 then
Result := GetLastChild(ItemParent.Items[I])
else
Result := ItemParent;
end
else if (Parent <> nil) and (Parent is TTreeView) then
begin
TreeViewParent := TTreeView(Parent);
I := 0;
while (I < TreeViewParent.Count) and (TreeViewParent.Items[I] <> Item) do
inc(I);
dec(I);
if I >= 0 then
Result := GetLastChild(TreeViewParent.Items[I])
else
Result := Item
end
else
Result := Item;
end;
end;

关于delphi - Firemonkey和Delphi XE3下如何顺序浏览TTreeView的所有节点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14647795/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com