有没有TreeView控件的典型或者实际用途用法及其示例代码或截图,可以是静态、动态创建生成树形结构的(除了文件系统目录树)

ooolinux 2019-08-29 06:04:11
有没有TreeView控件的典型或者实际用途用法及其示例代码或截图,可以是静态、动态创建生成树形结构的(除了文件系统目录树)
...全文
249 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
ooolinux 2019-09-11
  • 打赏
  • 举报
回复
我忘了,TTreeNode是没有Tag属性的,有个Data属性。
ooolinux 2019-08-30
  • 打赏
  • 举报
回复
引用 10 楼 天行归来 的回复:
[quote=引用 8 楼 ooolinux 的回复:] [quote=引用 4 楼 天行归来 的回复:] 有折腾了一套客户端,对接自己的 java 后端,有涉及到这些东东,可以参考下。 系统功能定义,className是窗体名称,用于动态实例化相应窗体类,窗体里的具体功能权限约束,是由接口决定是否可调用。如下:
你这个蛮复杂的~[/quote] 这个是我一个客户端框架里的代码,因为相对我自己不同项目可以通用,所以复杂。[/quote] 你这个点击树结点来执行功能是怎么个原理?
ooolinux 2019-08-29
  • 打赏
  • 举报
回复
想多了解一下TreeView控件。
ooolinux 2019-08-29
  • 打赏
  • 举报
回复
引用 1 楼 秋天之落叶 的回复:
不知道你需要什么,这个是你想要的吗? procedure TFormMain.FormShow(Sender: TObject); var i, j: Integer; c: TTreeNode; s: string; begin TreeView1.Items.Clear; for i := 0 to MainMenu1.Items.count - 1 do begin if Pos('(&', MainMenu1.Items[i].Caption) > 0 then s := Copy(MainMenu1.Items[i].Caption, 1, Pos('(&', MainMenu1.Items[i].Caption) - 1) else s := MainMenu1.Items[i].Caption; c := TreeView1.Items.Add(nil, s); for j := 0 to MainMenu1.Items[i].count - 1 do TreeView1.Items.AddChild(c, MainMenu1.Items[i].Items[j].Caption); end; TreeView1.FullExpand; end;
还可以,你这个是把菜单功能复制到TreeView上去,好像没有OnClick?
天行归来 2019-08-29
  • 打赏
  • 举报
回复
引用 8 楼 ooolinux 的回复:
[quote=引用 4 楼 天行归来 的回复:] 有折腾了一套客户端,对接自己的 java 后端,有涉及到这些东东,可以参考下。 系统功能定义,className是窗体名称,用于动态实例化相应窗体类,窗体里的具体功能权限约束,是由接口决定是否可调用。如下:
你这个蛮复杂的~[/quote] 这个是我一个客户端框架里的代码,因为相对我自己不同项目可以通用,所以复杂。
秋天之落叶 2019-08-29
  • 打赏
  • 举报
回复
不知道你需要什么,这个是你想要的吗?
procedure TFormMain.FormShow(Sender: TObject);
var
i, j: Integer;
c: TTreeNode;
s: string;
begin
TreeView1.Items.Clear;
for i := 0 to MainMenu1.Items.count - 1 do
begin
if Pos('(&', MainMenu1.Items[i].Caption) > 0 then
s := Copy(MainMenu1.Items[i].Caption, 1, Pos('(&', MainMenu1.Items[i].Caption) - 1)
else
s := MainMenu1.Items[i].Caption;
c := TreeView1.Items.Add(nil, s);
for j := 0 to MainMenu1.Items[i].count - 1 do
TreeView1.Items.AddChild(c, MainMenu1.Items[i].Items[j].Caption);
end;
TreeView1.FullExpand;
end;
ooolinux 2019-08-29
  • 打赏
  • 举报
回复
引用 5 楼 秋天之落叶 的回复:
procedure TFormMain.TreeView1Click(Sender: TObject); begin if (TreeView1.Selected.text = '关闭全部页面') then begin N1Click(Sender); end else if (TreeView1.Selected.text = '关闭当前页面') then begin N2Click(Sender); end ...... 点击节点我是这样用的,这样用的弊端是名字不能重复,但这样简单,我喜欢简单的。 以前是加一个判断,好像是index>0什么的,忘了。这个简单,一查就知道了。
这样看起来比较明了,可以再加个Tag属性来判断重复的名字。
ooolinux 2019-08-29
  • 打赏
  • 举报
回复
引用 4 楼 天行归来 的回复:
有折腾了一套客户端,对接自己的 java 后端,有涉及到这些东东,可以参考下。 系统功能定义,className是窗体名称,用于动态实例化相应窗体类,窗体里的具体功能权限约束,是由接口决定是否可调用。如下:
你这个蛮复杂的~
秋天之落叶 2019-08-29
  • 打赏
  • 举报
回复
引用 6 楼 天行归来 的回复:
[quote=引用 5 楼 秋天之落叶 的回复:]
procedure TFormMain.TreeView1Click(Sender: TObject);
begin
if (TreeView1.Selected.text = '关闭全部页面') then
begin
N1Click(Sender);
end
else if (TreeView1.Selected.text = '关闭当前页面') then
begin
N2Click(Sender);
end
......
点击节点我是这样用的,这样用的弊端是名字不能重复,但这样简单,我喜欢简单的。
以前是加一个判断,好像是index>0什么的,忘了。这个简单,一查就知道了。

最大的弊端是树的功能调用是硬编码[/quote]
我还没有优化到这里,暂时先这样用着,到时候再说,哈哈
天行归来 2019-08-29
  • 打赏
  • 举报
回复
引用 5 楼 秋天之落叶 的回复:
procedure TFormMain.TreeView1Click(Sender: TObject); begin if (TreeView1.Selected.text = '关闭全部页面') then begin N1Click(Sender); end else if (TreeView1.Selected.text = '关闭当前页面') then begin N2Click(Sender); end ...... 点击节点我是这样用的,这样用的弊端是名字不能重复,但这样简单,我喜欢简单的。 以前是加一个判断,好像是index>0什么的,忘了。这个简单,一查就知道了。
最大的弊端是树的功能调用是硬编码
秋天之落叶 2019-08-29
  • 打赏
  • 举报
回复
procedure TFormMain.TreeView1Click(Sender: TObject);
begin
if (TreeView1.Selected.text = '关闭全部页面') then
begin
N1Click(Sender);
end
else if (TreeView1.Selected.text = '关闭当前页面') then
begin
N2Click(Sender);
end
......
点击节点我是这样用的,这样用的弊端是名字不能重复,但这样简单,我喜欢简单的。
以前是加一个判断,好像是index>0什么的,忘了。这个简单,一查就知道了。
天行归来 2019-08-29
  • 打赏
  • 举报
回复

有折腾了一套客户端,对接自己的 java 后端,有涉及到这些东东,可以参考下。
系统功能定义,className是窗体名称,用于动态实例化相应窗体类,窗体里的具体功能权限约束,是由接口决定是否可调用。如下:

type
  PFunc = ^TFunc;
  TFunc = record
    id       : integer;
    code     : string;
    url      : string;
    className: string;
    showStyle: smallint;
    title    : string;
    funcs    : string;
    leaf     : smallint;
    remark   : string;
    enabled  : smallint;
  end;
  TFuncs = record
    count: integer;
    datas: array of TFunc;
  end;

以下代码为构建操作目录树:

class procedure TSMUIDrv.FreeFuncTV(const tv: TTreeView);
var
  i: Integer;
begin
	tv.OnChange := nil;
  for i:=0 to tv.Items.Count-1 do
  begin
    Dispose(PFunc(tv.Items[i].Data));
  end;
  tv.Items.Clear;
end;

function GetFuncParentNode(childNode: TTreeNode; childKey: string; ItemLen: Integer=1): TTreeNode;
var
  ParentKey: string;
  ParentNode: TTreeNode;
begin
  ParentKey := LeftStr(ChildKey,Length(ChildKey)-ItemLen);
  ParentNode := ChildNode;
  while ParentNode<>nil do
  begin
    if PFunc(ParentNode.Data)^.code = ParentKey then Break;
    ParentNode := ParentNode.Parent;
  end;
  Result := ParentNode;
end;

procedure BuildTreeFunNode(tv: TTreeView; funcs: string; buidFun: boolean; parentNode: TTreeNode);
var
  i: integer;
  lpFun: PFunc;
  jo: ISuperObject;
  ja: TSuperArray;
  newNode: TTreeNode;
begin
  if (not buidFun) or (funcs='') then exit;
  jo := TSMSystem.GetJsonObject(funcs);
  if jo=nil then exit;
  ja := jo.AsArray;
  if (ja=nil) or (ja.Length=0) then exit;

  for i:=0 to ja.Length-1 do
  begin
    newNode := tv.Items.AddChild(parentNode,TSMSystem.GetJsonValue(ja[i],'title',jsStr));
    new(lpFun);
    lpFun^.id := 0;
    lpFun^.code := TSMSystem.GetJsonValue(ja[i],'id',jsStr);
    newNode.Data := lpFun;
    newNode.SelectedIndex := 2;
    newNode.StateIndex := 2;
  end;
end;

class procedure TSMUIDrv.BuidFuncTV(tv: TTreeView; funcs: TFuncs; buildFun: boolean; root: string='');
var
  i: Integer;
  lpFun: PFunc;
  NewNode,ParentNode: TTreeNode;
begin
  NewNode := nil;
  FreeFuncTV(tv);
  if root<>'' then
  begin
    NewNode := tv.Items.AddChild(nil,root);
    new(lpFun);
    lpFun.title := root;
    lpFun^.code := '';
    lpFun^.leaf := 0;
    if tv.Images<>nil then
    begin
    	NewNode.ImageIndex := 0;
      NewNode.SelectedIndex := 0;
    	NewNode.StateIndex := 0;
    end;
    NewNode.Data := lpFun;
  end;
  for i:=0 to funcs.count-1 do
  begin
    if (funcs.datas[i].enabled<>1) then continue;
    ParentNode := GetFuncParentNode(NewNode,funcs.datas[i].code);
    NewNode := tv.Items.AddChild(ParentNode,funcs.datas[i].title);
    NewNode.ImageIndex := 1;
    NewNode.SelectedIndex := 2;
    NewNode.StateIndex := 2;
    new(lpFun);
    lpFun^ := funcs.datas[i];
    NewNode.Data := lpFun;
    BuildTreeFunNode(tv,funcs.datas[i].funcs,buildFun,newNode);
  end;
end;

以下代码为动态执行树对应的功能(发消息到主窗体统一执行):

procedure TFmNavicate.OnExecFunc(sender: TObject);
var
  func: TFunc;
  node: TTreeNode;
  level: integer;
begin
  if lvFuns.Selected<>nil then
  begin
    func := PFunc(lvFuns.Selected.Data)^;
    if func.className<>'' then
    begin
      SendMessage(FmMain.Handle,WM_EXECUTE_FUN,Integer(@func),0);
    end;
    node := FNavTree.Selected;
    level:= node.Level;
    if func.leaf=0 then
    begin
      while (node<>nil) and (node.Level>=level) do
      begin
        if PFunc(node.Data)^.code=func.code then
        begin
          node.Selected := true;
          node.Expand(true);
          break;
        end;
        node := node.GetNext;
      end;
    end;
  end;
end;

主窗体执行相应功能:


procedure TFmMain.OnExecuteTvFunc(sender: TObject);
var
  func: TFunc;
begin
  if tvFunc.Selected<>nil then
  begin
    func := PFunc(tvFunc.Selected.Data)^;
    TSMUIDrv.LoadFuncForm(pcCtl, func.className, func.showStyle);
  end;
end;


动态创建窗体:

class function TSMUIDrv.LoadFuncForm(parent: TRzPageControl; clsName: string; showStyle: smallint): TAWin;
var
  i,j: integer;
  tmp: TComponent;
  sht: TRzTabSheet;
begin
  if (showStyle=1) then
  begin
    tmp := LoadComponent(clsName,nil);
    if tmp<>nil then
    begin
      result := TAWin(tmp);
      result.ShowModal;
      result.Free;
    end;
    result := nil;
    exit;
  end;
  
  //form exists?
  for i:=0 to parent.PageCount-1 do
  begin
    for j:=0 to parent.Pages[i].ControlCount-1 do
    begin
      if parent.Pages[i].Controls[j].ClassName=clsName then
      begin
        parent.ActivePageIndex := i;
        result := TAWin(parent.Pages[i].Controls[j]);
        exit;
      end;
    end;
  end;
  //to load new form
  sht := TRzTabSheet.Create(parent);
  sht.PageControl := parent;
  tmp := LoadComponent(clsName,sht);
  if tmp<>nil then
  begin
    result := TAWin(tmp);
    result.Parent := sht;
    TAWin(tmp).BorderStyle := bsNone;
    sht.Caption := TAWin(tmp).Caption;
    result.Align  := alClient;
    sht.Tag := TAWin(tmp).Tag;
    result.Show;
    parent.ActivePageIndex := parent.PageCount-1;
  end
  else begin
    sht.Free;
    result := nil;
  end;
end;

效果图及主要数据表配置:

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧