TTreeView完整的枚举和递归算法

TTreeView完整的枚举和递归算法

 

一、TTreeView

(一)、重要属性

Memo_Test.Lines.Add(

      ‘TTreeView重要属性:’

    +',1、可见数:'+IntToStr((LAddObject as TTreeViewItem).VisibleCount)        //:该节点所有展开的下级总数
    +',2、Item个数:'+IntToStr((LAddObject as TTreeViewItem).Count)                //:该节点所有下级总数>=0,末级Count=0
    +',3、几级:'+IntToStr((LAddObject as TTreeViewItem).Level)                       //:该节点的级数:级数>=1 
    +',4、全局索引:'+IntToStr((LAddObject as TTreeViewItem).GlobalIndex)     //:该节点所有展开的下级的重新的自动索引(作用不大)

);

5、该节点的父节点:

     (LAddObject as TTreeViewItem).ParentItem

6、该节点被勾选IsChecked:

     if (LAddObject as TTreeViewItem).IsChecked=True then ;

7、该节点是否展开其下级、展开或收拢其下级:

  if FTreeViewItemCurrt.IsExpanded=false then
    FTreeViewItemCurrt.IsExpanded:=true
  else FTreeViewItemCurrt.IsExpanded:=false;

8、TreeView展开或收拢所有下级:

  FIFCollapse:=not FIFCollapse;
  if FIFCollapse=false then
    TreeView.CollapseAll       //收拢
  else TreeView.ExpandAll;  //展开

9、TreeView改变了勾选状态:

  procedure TreeViewChangeCheck(Sender: TObject);

  begin

     if (LAddObject as TTreeViewItem).IsChecked=True then ;  //:该节点改变了勾选状态

     if (LAddObject as TTreeViewItem).ParentItem.IsChecked=True then ;  //:该节点的父节点改变了勾选状态

  end;

10、TreeView的某节点被点击:

  LTreeViewItem.OnClick:=LAddObjectOnClick;  //:定义某节点的点击事件:LAddObjectOnClick:写代码

11、TreeView的动态增加节点:

  LTreeViewItem:=TTreeViewItem.Create( AOwnerObject );  //:所有者:应为窗体或TFrame
  LTreeViewItem.Index:=AIndex;      //:11.1、索引会被TTreeView的节点自动索引所覆盖:应使用自定义索引LTreeViewItem.Tag
  LTreeViewItem.Name:=AName;    //:11.2、节点命名:不能重复
  LTreeViewItem.Text:=AText;          //:11.3、节点的显示文本
  LTreeViewItem.Parent:=AParent;  //:11.4、父组件:关键:父组件可以是TreeView,也可以是某个TreeViewItem节点
      //LTreeViewItem.TagString:=ATreeFiledName.Trim+'='+AParent.Name;
  LTreeViewItem.TagString:=ATreeFiledName.Trim+'='+AText;    //:11.5、节点的个性化标签文字
  LTreeViewItem.ImageIndex:=ImageIndex;                                 //:11.6、节点的个性化图片索引

  LTreeViewItem.Tag:=AIndex;          //:11.7、自定义索引LTreeViewItem.Tag
  SetLength(FTreeViewItemCheckedCount,LTreeViewItem.Tag+1);  //:11.8:TreeViewItem被勾中的数组长度
  FTreeViewItemCheckedCount[LTreeViewItem.Tag]:=0;         //:初始化TreeViewItem被勾中的数组
       //:初始化TreeViewItem被勾中的数组TreeView.OnChangeCheck


    ///<summary>动态新增TreeView的TreeViewItem节点:</summary>

function TForm2.CreateATreeViewItems(
const AIndex:Integer;
      AName:string;
      AText:string;
      ATreeFiledName:string;
      AParent:TFmxObject;
      //:非常关键的参数:指明该节点:
        //:其父节点是TTreeView还是它的上级递归TTreeViewItem
      ImageIndex:Integer;
      ASizeHeight,ASizeWidth:Single;
      MarginsLeft:Single;
      AOwnerObject:TFmxObject
  ):TTreeViewItem;
var LTreeViewItem:TTreeViewItem;
begin
  InitATreeViewItems(TreeView_WorkSpace_Menus,FIFInited);

  LTreeViewItem:=TTreeViewItem.Create( AOwnerObject ); //:所有者:应为窗体或TFrame
  LTreeViewItem.Index:=AIndex;//:索引会被TTreeView的节点自动索引所覆盖:应使用自定义索引LTreeViewItem.Tag
  LTreeViewItem.Name:=AName;  //:节点命名:不能重复
  LTreeViewItem.Text:=AText;  //:节点的显示文本
  LTreeViewItem.Parent:=AParent;//:父组件:关键:父组件可以是TreeView,也可以是某个TreeViewItem节点
  //LTreeViewItem.TagString:=ATreeFiledName.Trim+'='+AParent.Name;
  LTreeViewItem.TagString:=ATreeFiledName.Trim+'='+AText;  //:节点的个性化标签文字
  LTreeViewItem.ImageIndex:=ImageIndex;   //:节点的个性化图片索引

  LTreeViewItem.Tag:=AIndex;  //:自定义索引LTreeViewItem.Tag
  SetLength(FTreeViewItemCheckedCount,LTreeViewItem.Tag+1);
  FTreeViewItemCheckedCount[LTreeViewItem.Tag]:=0;
    //:初始化TreeViewItem勾中数组TreeView.OnChangeCheck
  LTreeViewItem.Align:=TAlignLayout.Left;
  LTreeViewItem.IsChecked:=false;
  LTreeViewItem.IsExpanded:=false;
  LTreeViewItem.IsSelected:=false;
  LTreeViewItem.StyleLookup:='treeviewitemstyle';
  LTreeViewItem.StyledSettings:=
    LTreeViewItem.StyledSettings-
    [TStyledSetting.Family,
     TStyledSetting.Size,
     TStyledSetting.FontColor,
     TStyledSetting.Other
    ];
  LTreeViewItem.TextSettings.FontColor
    :=TAlphaColor($FF1373A9);
  LTreeViewItem.TextSettings.Font.Family:='微软雅黑';
  LTreeViewItem.TextSettings.Font.Size:=16;
  LTreeViewItem.Size.Height:=ASizeHeight;
  LTreeViewItem.Size.Width:=ASizeWidth;
  LTreeViewItem.Margins.Left:=MarginsLeft;
  LTreeViewItem.Position.Y:=AIndex*40;

  LTreeViewItem.IsExpanded:=false;
  LTreeViewItem.OnClick:=LAddObjectOnClick;

  Result:=LTreeViewItem;
end;

(二)、关键处理好

12、if   (LAddObject as TTreeViewItem).Level=1  then ;   //:处理好顶级

13、if  ( (LAddObject as TTreeViewItem).Level=1) and ((LAddObject as TTreeViewItem).Count>0)  then ;   //:处理好顶级但非末级的节点

14、if  ( (LAddObject as TTreeViewItem).Level=1) and ((LAddObject as TTreeViewItem).Count=0)  then ;   //:处理好顶级且为末级的节点

15、if  ( (LAddObject as TTreeViewItem).Level>1) and ((LAddObject as TTreeViewItem).Count>0)  then ;   //:处理好中间级的节点

16、if  ( (LAddObject as TTreeViewItem).Level>1) and ((LAddObject as TTreeViewItem).Count=0)  then ;   //:处理好非顶级且为末级的节点

二、TTreeView枚举其下被勾选的节点

procedure TForm2.ControlAction_btnEnumCheckedExecute(Sender: TObject);
begin
//遍历TreeView选中的节点:
  FTreeViewSelectAllOrNot:=false;
  EnumChecked(false,FTreeViewSelectAllOrNot);
end;


function TForm2.EnumChecked(
  const AIFAncester:Boolean=true;
        AIFUpdateCheckedStatus:Boolean=true):TStringList;
var LAddObject:TFmxObject;
    LStringList:TStringList;
    LCircle:Integer;
    LSeparator: array of char;
    LLineOfStringList :TArray<string>;
begin
//枚举TreeView选中的节点并决定是否变更选中状态:
  LStringList:=TStringList.Create;
  LTreeViewItemCount:=0;
  try
    TreeView_WorkSpace_Menus.EnumControls(
      procedure (const AControl: TControl; var Done: boolean)
      begin
        if (AControl.ClassName = 'TTreeViewItem') then
        begin
          LAddObject:=TTreeViewItem(AControl);
          if (AIFUpdateCheckedStatus=true) then
          begin
            if (LAddObject as TTreeViewItem).IsChecked=True then
              (LAddObject as TTreeViewItem).IsChecked:=false
            else (LAddObject as TTreeViewItem).IsChecked:=True;
          end;
          if (LAddObject as TTreeViewItem).IsChecked=True then
          begin
            if (AIFAncester=true) then
            begin
              if (LAddObject.TagString).Substring(
                   (LAddObject.TagString).IndexOf('=')+1
                  ,length(LAddObject.TagString) )=(LAddObject as TTreeViewItem).Text
              then
                LStringList.Add(LAddObject.TagString);
                //:格式:LTreeViewItem.TagString:=ATreeFiledName.Trim+'='+AParent.Name;
            end else
            if (AIFAncester=false) then
            begin
              if ( (LAddObject as TTreeViewItem).Count=0 )
              then //:找到末级反推上级
              begin
                if (LAddObject as TTreeViewItem).Level>1 then
                begin
                  if ((LAddObject as TTreeViewItem).ParentItem.Count
                    =FTreeViewItemCheckedCount[(LAddObject as TTreeViewItem).ParentItem.Tag]) then
                  begin //:找到了上级打勾:即下级全打勾
                    if LStringList.Text.Contains((LAddObject as TTreeViewItem).ParentItem.TagString)
                      =false then
                    begin
                      //Memo_Test.Lines.Add('找到了上级打勾');
                      LStringList.Add((LAddObject as TTreeViewItem).ParentItem.TagString);
                    end;
                    Done:=false;
                  end else
                  begin //:else:找到了只有个别下级打勾
                    if LStringList.Text.Contains((LAddObject as TTreeViewItem).TagString)
                      =false then
                    begin
                      //Memo_Test.Lines.Add('找到了只有个别下级打勾');
                      LStringList.Add((LAddObject as TTreeViewItem).TagString);
                    end;
                    Done:=false;
                  end;
                end;
                if (LAddObject as TTreeViewItem).Level=1 then
                begin //:末级是顶级
                  if LStringList.Text.Contains((LAddObject as TTreeViewItem).TagString)
                    =false then
                  begin
                    //Memo_Test.Lines.Add('找到了末级是顶级的节点');
                    LStringList.Add((LAddObject as TTreeViewItem).TagString);
                  end;
                  Done:=false;
                end;
              end;
              //:格式:LTreeViewItem.TagString:=ATreeFiledName.Trim+'='+AText;
            end;
          end;
        end;
        Done:=false;//:不要停继续找下一个
      end
      ,true //:只枚举可见的组件
    );
    //LStringList.Sort; //:枚举类型只能按照索引号index排序
    //LStringList的调用方法如下(可传递给sql条件拼接):测试枚举结果:
    //{
    //Memo_Test.Lines.Clear;
    Memo_Test.BringToFront; Memo_Test.Visible:=true;
    Memo_Test.Position.X:=361;
    Memo_Test.BeginUpdate;
    SetLength(LSeparator,1);
    LSeparator[0]:='=';
    for LCircle := 0 to LStringList.Count-1 do
    begin
      SetLength(LLineOfStringList,length(LStringList[LCircle]));
      LLineOfStringList[0]:=LStringList[LCircle].Split(LSeparator[0])[0];
      LLineOfStringList[1]:=LStringList[LCircle].Split(LSeparator[0])[1];
      Memo_Test.Lines.Add(LLineOfStringList[0]+'='+LLineOfStringList[1]);
      //Memo_Test.Lines.Add(LStringList[LCircle]);
    end;
    Memo_Test.EndUpdate; //}
    Result:=LStringList;
  finally
    FreeAndNil(LStringList);
  end;

end;

 

三、TTreeView与枚举和递归算法:TTreeView枚举并递归加载外部数据源

    ///<summary>某节点TTreeViewItem被勾中或取消勾中处理其节点及其上下级节点:</summary>


procedure TForm2.TreeView_WorkSpace_MenusChangeCheck(Sender: TObject);
var LLevel:Integer;

  procedure LEnumControls(LFmxObject:TFmxObject;EnumControlClassName:string);
  begin
    //1、处理ChangeCheck的上级:
    if (LFmxObject as TTreeViewItem).IsChecked=true then
    begin
      if (LLevel>1) then//:基线条件
      begin
        try
          if FTreeViewItemCheckedCount[FTreeViewItemTag]
            < (LFmxObject as TTreeViewItem).ParentItem.Count then
          begin
            if LErgodicParent<>'父已枚举' then
              INC(FTreeViewItemCheckedCount[FTreeViewItemTag]);
            //:上级+1
            LErgodicParent:='';
            Memo_Test.Lines.Add('枚举对象:'+(Sender as TTreeViewItem).Text+':上级:'+(Sender as TTreeViewItem).ParentItem.Text+':被勾中数:'+IntToStr(FTreeViewItemCheckedCount[FTreeViewItemTag]) );
          end;
        finally
          if FTreeViewItemCheckedCount[FTreeViewItemTag]
            = (Sender as TTreeViewItem).ParentItem.Count then
          begin
            LErgodicParent:='父已枚举';
            if (Sender as TTreeViewItem).ParentItem.IsChecked=false then
              (Sender as TTreeViewItem).ParentItem.IsChecked:=true;
            //:开始递归:上级枚举
          end;
        end;
      end else
      if (LLevel=1) then//:基线条件
      begin
        if FTreeViewItemCheckedCount[FTreeViewItemTag]
          < (LFmxObject as TTreeViewItem).Count then
        begin
          if LErgodicParent<>'父已枚举' then
            INC(FTreeViewItemCheckedCount[FTreeViewItemTag]);
          //:上级+1
          LErgodicParent:='';
          Memo_Test.Lines.Add('枚举对象:'+(Sender as TTreeViewItem).Text+':上级:'+(Sender as TTreeViewItem).Text+':被勾中数:'+IntToStr(FTreeViewItemCheckedCount[FTreeViewItemTag]) );
        end;
      end;
    end else
    if (LFmxObject as TTreeViewItem).IsChecked=false then
    begin
      if (LLevel>1) then//:基线条件
      begin
        try
          if FTreeViewItemCheckedCount[FTreeViewItemTag]
            >0 then
          begin
            if LErgodicParent<>'父已枚举' then
              DEC(FTreeViewItemCheckedCount[FTreeViewItemTag]);
            //:上级-1
            LErgodicParent:='';
            Memo_Test.Lines.Add('枚举对象:'+(Sender as TTreeViewItem).Text+':上级:'+(Sender as TTreeViewItem).ParentItem.Text+':被勾中数:'+IntToStr(FTreeViewItemCheckedCount[FTreeViewItemTag]) );
          end;
        finally
          if FTreeViewItemCheckedCount[FTreeViewItemTag]
            = 0 then
          begin
            LErgodicParent:='父已枚举';
            if (Sender as TTreeViewItem).ParentItem.IsChecked=true then
              (Sender as TTreeViewItem).ParentItem.IsChecked:=false;
            //:开始递归:上级枚举
          end;
        end;
      end else
      if (LLevel=1) then//:基线条件
      begin
        if FTreeViewItemCheckedCount[FTreeViewItemTag]
          >0 then
        begin
          if LErgodicParent<>'父已枚举' then
            DEC(FTreeViewItemCheckedCount[FTreeViewItemTag]);
          //:上级-1
          LErgodicParent:='';
          Memo_Test.Lines.Add('枚举对象:'+(Sender as TTreeViewItem).Text+':上级:'+(Sender as TTreeViewItem).Text+':被勾中数:'+IntToStr(FTreeViewItemCheckedCount[FTreeViewItemTag]) );
        end;
      end;
    end;
    //2、处理ChangeCheck的本级枚举:
    try
      LErgodicParent:='';
      LFmxObject.EnumObjects(//const Proc: TFunc<TFmxObject, TEnumProcResult>
        function (LControl:TFmxObject):TEnumProcResult
          var LEnumProcResult:TEnumProcResult;
        begin
          //2.1、处理ChangeCheck的本级枚举到其下级:
          if LControl.ClassName=EnumControlClassName then
          begin
            if EnumControlClassName='TTreeViewItem' then
            begin
              if (LFmxObject as TTreeViewItem).IsChecked=true then
              begin
                //Memo_Test.Lines.Add('枚举到了下级');
                if (LControl as TTreeViewItem).IsChecked=false then
                begin
                  (LControl as TTreeViewItem).IsChecked:=true;
                end;
                  //:开始递归:(本级有下级)中间级枚举
              end;
              if (LFmxObject as TTreeViewItem).IsChecked=false then
              begin
                if (LControl as TTreeViewItem).IsChecked=true then
                begin
                  (LControl as TTreeViewItem).IsChecked:=false;
                end;
                  //:开始递归:(本级有下级)中间级枚举
              end;
            end;
          end;
          //2.1、处理ChangeCheck的本级枚举为末级:
          if LControl.ClassName<>EnumControlClassName then
          begin
            //Memo_Test.Lines.Add('末级被勾中:没有枚举到下级');
            //Memo_Test.Lines.Add('枚举对象:'+(LFmxObject as TTreeViewItem).Text+':上级:'+(LFmxObject as TTreeViewItem).ParentItem.Text+':被勾中数:'+IntToStr(FTreeViewItemCheckedCount[FTreeViewItemTag]) );
          end;
          Result:=TEnumProcResult.Continue;//:直到再无可枚举的下级

        end
      );
    finally
    end;

  end;
begin
  if FIFInited=false then exit//:必须先完成初始化: 初始化在Checked:=false
  else
  begin
    LLevel:=(Sender as TTreeViewItem).Level;
    if (LLevel=1) then
    begin
      FTreeViewItemTag:=(Sender as TTreeViewItem).Tag;
      //1、枚举子节点及其下级节点,自动勾或去勾:
      //:同时子节点会开始递归本单元:
      LEnumControls((Sender as TTreeViewItem),'TTreeViewItem');
    end else
    if (LLevel>1) then
    begin
      FTreeViewItemTag:=(Sender as TTreeViewItem).ParentItem.Tag;
      //1、枚举子节点及其下级节点,自动勾或去勾:
      //:同时子节点会开始递归本单元:
      LEnumControls((Sender as TTreeViewItem),'TTreeViewItem');
    end;

  end;
end;

四、TreeView父Item和子Item勾选互动:

  TTreeView = class(TCustomTreeView)
  published
       property OnChangeCheck;  //.....(还有很多发布属性)
           //:该属性的父类为受保护属性:  protected TCustomTreeView.OnChangeCheck
   end;

  TMyTreeView =Class(TTreeView)
  private
  protected
  public
  published
       // 我要改写并将其发布出来供调用者和RttiType使用:
       procedure OnChangeCheck( AItem :TObject );//:protected TCustomTreeView.OnChangeCheck
  end;
  // 实现代码如下:

implementation

{$R *.fmx}
{TMyTreeView}
procedure TMyTreeView.OnChangeCheck( AItem :TObject );
var LLoop,
    LCountAllCheckedOfAParentItem,
    LCountAllUnCheckedOfAParentItem :Integer;
    LItem,
    LParentItem: TTreeViewItem;
begin
  inherited DoChangeCheck( AItem as TTreeViewItem );
      {
      procedure TCustomTreeView.DoChangeCheck( const Item: TTreeViewItem );
      begin
        if Assigned(FOnChangeCheck) then
          FOnChangeCheck(Item);
      end;
      }  

  LItem := TTreeViewItem(AItem as TTreeViewItem);
  for LLoop:=0 to LItem.Count - 1 do
     LItem.Items[LLoop].IsChecked := LItem.IsChecked;
  if TTreeViewItem(LItem).ParentItem<>nil then
  begin
    LParentItem :=TTreeViewItem(LItem).ParentItem;
    LCountAllCheckedOfAParentItem:=0;
    for LLoop:=0 to LParentItem.Count - 1 do
      if LParentItem.Items[LLoop].IsChecked=true then
        LCountAllCheckedOfAParentItem
          :=LCountAllCheckedOfAParentItem+1;
    if LCountAllCheckedOfAParentItem=LParentItem.Count then
    begin
      LParentItem.IsChecked:=true;
    end;
    LCountAllUnCheckedOfAParentItem:=LParentItem.Count;
    for LLoop:=0 to LParentItem.Count - 1 do
      if LParentItem.Items[LLoop].IsChecked=false then
        LCountAllUnCheckedOfAParentItem
          :=LCountAllUnCheckedOfAParentItem-1;
    if LCountAllUnCheckedOfAParentItem=0 then
    begin
      LParentItem.IsChecked:=false;
    end;
  end;
end;

//  调用代码:
procedure TForm2.FormCreate(Sender: TObject);
var LTreeView :TMyTreeView;
begin
    LTreeView :=TMyTreeView.Create(TreeView1);  // :TreeView1 :UI中的TreeView组件
    TreeView1.OnChangeCheck :=LTreeView.OnChangeCheck;
end; 

五、TTreeView枚举与递归效果

 

 

 

 

06-22
### 得物技术栈及开发者文档分析 得物作为一家专注于潮流商品的电商平台,其技术栈和开发者文档主要围绕电商平台的核心需求展开。以下是对得物技术栈及相关开发资源的详细解析: #### 1. 技术栈概述 得物的技术栈通常会涵盖前端、后端、移动应用开发以及大数据处理等多个领域。以下是可能涉及的主要技术栈[^3]: - **前端开发**: 前端技术栈可能包括现代框架如 React 或 Vue.js,用于构建高效、响应式的用户界面。此外,还会使用 Webpack 等工具进行模块化打包和优化。 - **后端开发**: 后端技术栈可能采用 Java Spring Boot 或 Node.js,以支持高并发和分布式架构。数据库方面,MySQL 和 Redis 是常见的选择,分别用于关系型数据存储和缓存管理。 - **移动应用开发**: 得物的移动应用开发可能基于原生技术(如 Swift/Kotlin)或跨平台框架(如 Flutter)。这有助于确保移动端应用的性能和用户体验一致性。 - **大数据云计算**: 在大数据处理方面,得物可能会使用 Hadoop 或 Spark 进行数据挖掘和分析。同时,依托云服务提供商(如阿里云或腾讯云),实现弹性扩展和资源优化。 #### 2. 开发者文档分析 类似于引用中提到的 Adobe 开发者文档模板[^2],得物也可能提供一套完整的开发者文档体系,以支持内部团队协作和外部开发者接入。以下是开发者文档可能包含的内容: - **API 文档**: 提供 RESTful API 或 GraphQL 的详细说明,帮助开发者快速集成得物的功能模块,例如商品搜索、订单管理等。 - **SDK 集成指南**: 针对不同平台(如 iOS、Android 或 Web)提供 SDK 下载和集成教程,简化第三方应用的开发流程。 - **技术博客**: 分享得物在技术实践中的经验成果,例如如何优化图片加载速度、提升应用性能等。 - **开源项目**: 得物可能将部分技术成果开源,供社区开发者学习和贡献。这不仅有助于提升品牌形象,还能吸引更多优秀人才加入。 #### 3. 示例代码 以下是一个简单的示例代码,展示如何通过 RESTful API 调用得物的商品搜索功能(假设接口已存在): ```python import requests def search_items(keyword, page=1): url = "https://api.dewu.com/v1/items/search" headers = { "Authorization": "Bearer YOUR_ACCESS_TOKEN", "Content-Type": "application/json" } params = { "keyword": keyword, "page": page, "size": 10 } response = requests.get(url, headers=headers, params=params) if response.status_code == 200: return response.json() else: return {"error": "Failed to fetch data"} # 调用示例 result = search_items("Air Jordan", page=1) print(result) ``` 此代码片段展示了如何通过 Python 请求得物的 API,并获取指定关键词的商品列表。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

专讲冷知识

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值