• Delphi实现树型结构


    生成树型结构有2种方法:

    1.动态生成树结点

    2.静态生成树结点

    这里暂不讨论动态生成树,先实现静态生成!

    所谓静态生成树结点是指通过遍历数据源的方式一次性把所有树结点全部加载,说起生成树避免不了谈起数据库结构的设计。

    数据库设计的方法有2种:

    1.单编号法

    单编号法是以每个类为统一编号,如其有子类,则顺着该编号向后排。如水果编号为001,则苹果为水果的一类,则应为001001等等,这种方法易于统计,但不易于维护!如:想要将苹果类变为其它的类,且苹果类下有N层,那会是一件比较麻烦的事情!

    2.双编号法

    双编号也就是我们经常说的用ID与PARENTID来表示其父子关系,维护起来比较方便,但遍历会稍稍复杂一些!

    无论哪种方法,一般情况下都要创建结构体,并把结构体指针放置到树结点中!因为Treeview的树结点不可能放

    置更多的信息,我们通常要存该结点的名称(中英文)、结点ID、是否为功能结点、父结点、图标、选中结点后的图标、dll的名称等等等...

    以下例子:

      1 01.unit Unit1;  
    2 02.interface
    3 03.uses
    4 04. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    5 05. Dialogs, StdCtrls, ComCtrls, DB, ADODB;
    6 06.type
    7 07. PNodeInfoEx = ^TNodeInfoEx;
    8 08. TNodeInfoEx = Packed Record
    9 09. NodeID : Integer;
    10 10. ParentID : Integer;
    11 11. NodeType : Integer;
    12 12. ChnNodeTitle : String;
    13 13. ImageIndex: SmallInt;
    14 14. SelectedIndex: SmallInt;
    15 15. end;
    16 16. TForm1 = class(TForm)
    17 17. tv1: TTreeView;
    18 18. btn1: TButton;
    19 19. qry1: TADOQuery;
    20 20. procedure btn1Click(Sender: TObject);
    21 21. procedure FormDestroy(Sender: TObject);
    22 22. private
    23 23. { Private declarations }
    24 24. function StaticBuildTree(TreeView:TTreeView ):Boolean;
    25 25. function AddTreeItem(TreeView:TTreeView; AddNodeInfo:PNodeInfoEx):TTreeNode;
    26 26. function FindTreeItem(TreeView:TTreeView; CurNodeID:integer): TTreeNode;
    27 27. public
    28 28. { Public declarations }
    29 29. end;
    30 30.var
    31 31. Form1: TForm1;
    32 32.implementation
    33 33.{$R *.dfm}
    34 34.
    35 35.function TForm1.StaticBuildTree(TreeView:TTreeView ):Boolean;
    36 36.var
    37 37. AddNodeInfo : PNodeInfoEx;
    38 38.begin
    39 39. Result := False;
    40 40. qry1.LoadFromFile('c:/AdminixTree.xml');//这里以XML文件做为数据源
    41 41. Treeview.Items.BeginUpdate;//记住:在进行批量添加数据时要使用BeginUpdate,来暂时关闭由于添加数据而触发的某些事件(如OnChange事件等)
    42 42. Treeview.Items.Clear;//清空Treeview
    43 43. try
    44 44. try
    45 45. if qry1.RecordCount >0 then
    46 46. begin
    47 47. qry1.First;
    48 48. while Not qry1.Eof do
    49 49. begin
    50 50. New(AddNodeInfo) ;//生成结构体
    51 51. AddNodeInfo^.NodeID := qry1.FieldByName('NODE_ID').AsInteger;
    52 52. AddNodeInfo^.ParentID := qry1.FieldByName('PARENT_ID').AsInteger;
    53 53. AddNodeInfo^.NodeType := qry1.FieldByName('NodeType').AsInteger;
    54 54. AddNodeInfo^.ChnNodeTitle := qry1.FieldByName('ChnNodeTitle').AsString;
    55 55. AddNodeInfo^.ImageIndex := qry1.FieldByName('ImageIndex').AsInteger;
    56 56. AddNodeInfo^.SelectedIndex := qry1.FieldByName('SelectedIndex').AsInteger;
    57 57. AddTreeItem(Treeview,AddNodeInfo);//把结构体的指针存到Treeview中
    58 58. qry1.Next;
    59 59. end;
    60 60. end;
    61 61. except
    62 62. Application.MessageBox('生成树结点失败',MB_ICONSTOP+MB_OK);
    63 63. raise;//向上级抛异常
    64 64. end;
    65 65. qry1.Close;
    66 66. Result := True;
    67 67. finally
    68 68. Treeview.Items.EndUpdate;
    69 69. end;
    70 70.end;
    71 71.//在加入结点时,应先判断加入的是父结点还是子结点,判断的依据是在已存在的树结点中是否存在该结点的ParentID
    72 72.function TForm1.AddTreeItem(TreeView:TTreeView; AddNodeInfo:PNodeInfoEx):TTreeNode;
    73 73.var
    74 74. ParentNode: TTreeNode;
    75 75.begin
    76 76. ParentNode := FindTreeItem(Treeview,AddNodeInfo^.ParentID);
    77 77. If ParentNode <> nil then
    78 78. Result := Treeview.Items.AddChildObject(ParentNode, Trim(AddNodeInfo.ChnNodeTitle), Pointer(AddNodeInfo))
    79 79. else
    80 80. Result := Treeview.Items.AddObject(ParentNode, Trim(AddNodeInfo.ChnNodeTitle), Pointer(AddNodeInfo));
    81 81. if Result<>nil then
    82 82. begin
    83 83. Result.ImageIndex := AddNodeInfo.ImageIndex;
    84 84. Result.SelectedIndex := AddNodeInfo.SelectedIndex;
    85 85. end;
    86 86.end;
    87 87.//这里是判断是否存在其父结点
    88 88.function TForm1.FindTreeItem(TreeView:TTreeView; CurNodeID:integer): TTreeNode;
    89 89.var
    90 90. i : Integer;
    91 91.begin
    92 92. Result := nil;
    93 93. for i := 0 to Treeview.Items.Count-1 do
    94 94. begin
    95 95. if CurNodeID=PNodeInfoEx(Treeview.Items[i].Data)^.NodeID then
    96 96. begin
    97 97. Result := Treeview.Items[i];
    98 98. Exit;
    99 99. end;
    100 100. end;
    101 101.end;
    102 102.//生成树结构
    103 103.procedure TForm1.btn1Click(Sender: TObject);
    104 104.begin
    105 105. StaticBuildTree (tv1)
    106 106.end;
    107 107.//在窗体释放时一定要把树结点中的结构体指针给释放掉,对于在Dispose时为什么要进行强制转型后释放,以前有专门的讲解,在此不在累述
    108 108.procedure TForm1.FormDestroy(Sender: TObject);
    109 109.var
    110 110. i : Integer;
    111 111.begin
    112 112. for i := 0 to tv1.Items.Count-1 do
    113 113. begin
    114 114. Dispose( PNodeInfoEx(tv1.Items[i].Data) )
    115 115. end;
    116 116.end;
    117 117.end.
    118 01.//如何访问树结点?
    119 02.procedure TForm1.tv1MouseDown(Sender: TObject; Button: TMouseButton;
    120 03. Shift: TShiftState; X, Y: Integer);
    121 04.var
    122 05. pNode:TTreeNode;
    123 06.begin
    124 07. pNode:=tv1.GetNodeAt(x,y);
    125 08. if (pNode<>nil) and (Button=mbleft) then
    126 09. ShowMessage(PNodeInfoEx(pNode.Data)^.ChnNodeTitle);
    127 10.end;
    每天早上敲醒自己的不是闹钟,是夢想!
  • 相关阅读:
    poj 3348 Cows
    HDOJ4467 ( 分块 思想 )
    HDOJ 4858 项目管理 ( 只是有点 莫队的分块思想在里面而已啦 )
    luogu P1494 [国家集训队]小Z的袜子 ( 普 通 )
    CREATEINPUTLAYOUT_INCOMPATIBLEFORMAT
    load d3dcompiler_46.dll failed
    HDAO one error
    PS4 Razor GPU
    BLUR
    疑难杂症rendering(对角线上的线)
  • 原文地址:https://www.cnblogs.com/yplong/p/2360961.html
Copyright © 2020-2023  润新知