Delphi实现树型结构
2012-02-21 11:01
274 查看
生成树型结构有2种方法:
1.动态生成树结点
2.静态生成树结点
这里暂不讨论动态生成树,先实现静态生成!
所谓静态生成树结点是指通过遍历数据源的方式一次性把所有树结点全部加载,说起生成树避免不了谈起数据库结构的设计。
数据库设计的方法有2种:
1.单编号法
单编号法是以每个类为统一编号,如其有子类,则顺着该编号向后排。如水果编号为001,则苹果为水果的一类,则应为001001等等,这种方法易于统计,但不易于维护!如:想要将苹果类变为其它的类,且苹果类下有N层,那会是一件比较麻烦的事情!
2.双编号法
双编号也就是我们经常说的用ID与PARENTID来表示其父子关系,维护起来比较方便,但遍历会稍稍复杂一些!
无论哪种方法,一般情况下都要创建结构体,并把结构体指针放置到树结点中!因为Treeview的树结点不可能放
置更多的信息,我们通常要存该结点的名称(中英文)、结点ID、是否为功能结点、父结点、图标、选中结点后的图标、dll的名称等等等...
以下例子:
1.动态生成树结点
2.静态生成树结点
这里暂不讨论动态生成树,先实现静态生成!
所谓静态生成树结点是指通过遍历数据源的方式一次性把所有树结点全部加载,说起生成树避免不了谈起数据库结构的设计。
数据库设计的方法有2种:
1.单编号法
单编号法是以每个类为统一编号,如其有子类,则顺着该编号向后排。如水果编号为001,则苹果为水果的一类,则应为001001等等,这种方法易于统计,但不易于维护!如:想要将苹果类变为其它的类,且苹果类下有N层,那会是一件比较麻烦的事情!
2.双编号法
双编号也就是我们经常说的用ID与PARENTID来表示其父子关系,维护起来比较方便,但遍历会稍稍复杂一些!
无论哪种方法,一般情况下都要创建结构体,并把结构体指针放置到树结点中!因为Treeview的树结点不可能放
置更多的信息,我们通常要存该结点的名称(中英文)、结点ID、是否为功能结点、父结点、图标、选中结点后的图标、dll的名称等等等...
以下例子:
01.unit Unit1; 02.interface 03.uses 04. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 05. Dialogs, StdCtrls, ComCtrls, DB, ADODB; 06.type 07. PNodeInfoEx = ^TNodeInfoEx; 08. TNodeInfoEx = Packed Record 09. NodeID : Integer; 10. ParentID : Integer; 11. NodeType : Integer; 12. ChnNodeTitle : String; 13. ImageIndex: SmallInt; 14. SelectedIndex: SmallInt; 15. end; 16. TForm1 = class(TForm) 17. tv1: TTreeView; 18. btn1: TButton; 19. qry1: TADOQuery; 20. procedure btn1Click(Sender: TObject); 21. procedure FormDestroy(Sender: TObject); 22. private 23. { Private declarations } 24. function StaticBuildTree(TreeView:TTreeView ):Boolean; 25. function AddTreeItem(TreeView:TTreeView; AddNodeInfo:PNodeInfoEx):TTreeNode; 26. function FindTreeItem(TreeView:TTreeView; CurNodeID:integer): TTreeNode; 27. public 28. { Public declarations } 29. end; 30.var 31. Form1: TForm1; 32.implementation 33.{$R *.dfm} 34. 35.function TForm1.StaticBuildTree(TreeView:TTreeView ):Boolean; 36.var 37. AddNodeInfo : PNodeInfoEx; 38.begin 39. Result := False; 40. qry1.LoadFromFile('c:/AdminixTree.xml');//这里以XML文件做为数据源 41. Treeview.Items.BeginUpdate;//记住:在进行批量添加数据时要使用BeginUpdate,来暂时关闭由于添加数据而触发的某些事件(如OnChange事件等) 42. Treeview.Items.Clear;//清空Treeview 43. try 44. try 45. if qry1.RecordCount >0 then 46. begin 47. qry1.First; 48. while Not qry1.Eof do 49. begin 50. New(AddNodeInfo) ;//生成结构体 51. AddNodeInfo^.NodeID := qry1.FieldByName('NODE_ID').AsInteger; 52. AddNodeInfo^.ParentID := qry1.FieldByName('PARENT_ID').AsInteger; 53. AddNodeInfo^.NodeType := qry1.FieldByName('NodeType').AsInteger; 54. AddNodeInfo^.ChnNodeTitle := qry1.FieldByName('ChnNodeTitle').AsString; 55. AddNodeInfo^.ImageIndex := qry1.FieldByName('ImageIndex').AsInteger; 56. AddNodeInfo^.SelectedIndex := qry1.FieldByName('SelectedIndex').AsInteger; 57. AddTreeItem(Treeview,AddNodeInfo);//把结构体的指针存到Treeview中 58. qry1.Next; 59. end; 60. end; 61. except 62. Application.MessageBox('生成树结点失败',MB_ICONSTOP+MB_OK); 63. raise;//向上级抛异常 64. end; 65. qry1.Close; 66. Result := True; 67. finally 68. Treeview.Items.EndUpdate; 69. end; 70.end; 71.//在加入结点时,应先判断加入的是父结点还是子结点,判断的依据是在已存在的树结点中是否存在该结点的ParentID 72.function TForm1.AddTreeItem(TreeView:TTreeView; AddNodeInfo:PNodeInfoEx):TTreeNode; 73.var 74. ParentNode: TTreeNode; 75.begin 76. ParentNode := FindTreeItem(Treeview,AddNodeInfo^.ParentID); 77. If ParentNode <> nil then 78. Result := Treeview.Items.AddChildObject(ParentNode, Trim(AddNodeInfo.ChnNodeTitle), Pointer(AddNodeInfo)) 79. else 80. Result := Treeview.Items.AddObject(ParentNode, Trim(AddNodeInfo.ChnNodeTitle), Pointer(AddNodeInfo)); 81. if Result<>nil then 82. begin 83. Result.ImageIndex := AddNodeInfo.ImageIndex; 84. Result.SelectedIndex := AddNodeInfo.SelectedIndex; 85. end; 86.end; 87.//这里是判断是否存在其父结点 88.function TForm1.FindTreeItem(TreeView:TTreeView; CurNodeID:integer): TTreeNode; 89.var 90. i : Integer; 91.begin 92. Result := nil; 93. for i := 0 to Treeview.Items.Count-1 do 94. begin 95. if CurNodeID=PNodeInfoEx(Treeview.Items[i].Data)^.NodeID then 96. begin 97. Result := Treeview.Items[i]; 98. Exit; 99. end; 100. end; 101.end; 102.//生成树结构 103.procedure TForm1.btn1Click(Sender: TObject); 104.begin 105. StaticBuildTree (tv1) 106.end; 107.//在窗体释放时一定要把树结点中的结构体指针给释放掉,对于在Dispose时为什么要进行强制转型后释放,以前有专门的讲解,在此不在累述 108.procedure TForm1.FormDestroy(Sender: TObject); 109.var 110. i : Integer; 111.begin 112. for i := 0 to tv1.Items.Count-1 do 113. begin 114. Dispose( PNodeInfoEx(tv1.Items[i].Data) ) 115. end; 116.end; 117.end. 01.//如何访问树结点? 02.procedure TForm1.tv1MouseDown(Sender: TObject; Button: TMouseButton; 03. Shift: TShiftState; X, Y: Integer); 04.var 05. pNode:TTreeNode; 06.begin 07. pNode:=tv1.GetNodeAt(x,y); 08. if (pNode<>nil) and (Button=mbleft) then 09. ShowMessage(PNodeInfoEx(pNode.Data)^.ChnNodeTitle); 10.end;
相关文章推荐
- Delphi实现树型结构具体实例
- Delphi实现树型结构
- Delphi实现树型结构
- Delphi实现树型结构具体实例
- Delphi实现树型结构
- [导入](C#)如何实现磁盘文件以及目录树型结构显示(Longever原创)
- 基于AJAX的动态树型结构的设计与实现
- Delphi 7下使用VT实现树型列表结合控件
- C#实现树型结构TreeView节点拖拽的简单功能,附全部源码,供有需要的参考
- Delphi 7下使用VT实现树型列表结合控件
- 实现论坛树型结构的具体算法
- JSP实现论坛树型结构的具体算法
- [VB.NET]csdn上的论坛树型结构是怎么实现的呢 ??用的是什么技术和控件啊?
- 基于AJAX的动态树型结构的设计与实现
- vue.js树型结构实现
- asp实现树型结构
- 基于AJAX的动态树型结构的设计与实现
- 用数据库实现树型结构
- dropdownlist实现树型结构的栏目信息
- JSTL实现递归展示树型结构数据!