Delphi中根据分类数据生成树形结构的最优方法

上传人:平*** 文档编号:13300517 上传时间:2017-10-23 格式:DOC 页数:27 大小:218.27KB
返回 下载 相关 举报
Delphi中根据分类数据生成树形结构的最优方法_第1页
第1页 / 共27页
Delphi中根据分类数据生成树形结构的最优方法_第2页
第2页 / 共27页
Delphi中根据分类数据生成树形结构的最优方法_第3页
第3页 / 共27页
Delphi中根据分类数据生成树形结构的最优方法_第4页
第4页 / 共27页
Delphi中根据分类数据生成树形结构的最优方法_第5页
第5页 / 共27页
点击查看更多>>
资源描述

《Delphi中根据分类数据生成树形结构的最优方法》由会员分享,可在线阅读,更多相关《Delphi中根据分类数据生成树形结构的最优方法(27页珍藏版)》请在金锄头文库上搜索。

1、Delphi 中根据分类数据生成树形结构的最优方法1、 引言:TreeView 控件适合于表示具有多层次关系的数据。它以简洁的界面,表现形式清晰、形象,操作简单而深受用户喜爱。而且用它可以实现 ListView、ListBox 所无法实现的很多功能,因而受到广大程序员的青睐。树形结构在 Windows 环境中被普遍应用,但在数据库开发中面对层次多、结构复杂的数据,如何快速构造树形目录并实现导航呢?二、 实现关键技术:在 Delphi 提供的控件中包含了 TreeView 控件,但树的具体形成还需要用户编写代码。即它的列表项要在程序中动态添加,而这些列表数据通常由用户已录入在数据库表中,并作为数

2、据库维护的一项内容。许多人用 TreeView 构造树形目录时,通常都使用多个嵌套循环,或递归算法,将代码“编织”成树。这样不但算法复杂,且运行效率低下,不是最佳选择。这里介绍的是基于编码结构的高效算法。该算法的主要优点是:程序短小精悍,运行效率高,能快速实现数据库的树形结构,可以适应任何复杂的层次数据,实现方法简单,且树的内容有变动时,无需更改程序行。算法的关键在于代码字典表中的代码字段的设计上一定要符合一定的代码设计要求,数据类型使用字符型。用户新增和修改代码时,必须有严格的约束,否则会导致程序出错。编码表的基本字段包括编码和编码名称,其编码规则是以数字、字母的位数来区分不同层次,同一层编

3、码位数相同,层次按位数递增,程序通过判断编码位数来决定所在层数。本例程中编码结构是“222” ,编码格式为 “XX XX XX”。例如:第一层为1099两位,第二层为10011099四位,用户需要做的是先要设计树的结构和对应编码,并录入相应名称,然后程序在读取这些数据时形成树。本例程不需要用户自己进行编码,程序中自动实现各层编码,保证了代码格式的正确性。用 TreeView 导航表时,采用弹出式菜单,通过对话框操作数据表,同步更新树形控件和数据库。在所有操作中,树形控件不用重构,从而避免了重构时 TreeView 控件出现的闪动,也提高了程序的运行速度。本示例程序为了使大家看清楚数据表中记录是

4、否同步更新,用 TDBGrid 控件显示当前数据库表中所有记录。下面给出范例程序和主要代码分析。三、 范例程序和主要代码分析:我们以建立一个城市名称的树形结构为例来说明如何快速生成树形并实现导航数据表。1 先建立编码表:city_tree(bianma,cityname)。2 新建一个项目,按默认保存。3 新建一公共单元 pubvar,在其中定义以下常量:ConstcTreeCodeFormat = 222;/编码格式为 XX XX XXcTreeMaxLevel = 3;/最大编码层次cTreeRootTxt = 城市;/树根结点名称这样做为了提高程序的通用性,以后用于其他代码字典的维护时,

5、只需要更改这些特征常量。4 程序源代码:unit Unit1;interface usesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DB, DBTables, ImgList, ComCtrls , PubVar, Grids, DBGrids, Menus , StrUtils, StdCtrls;typeTForm1 = class(TForm)Tree: TTreeView;ImageList1: TImageList;Table1: TTable;DataSou

6、rce1: TDataSource;DBGrid1: TDBGrid;PopupMenu1: TPopupMenu;AddMenu: TMenuItem;DeleteMenu: TMenuItem;RenameMenu: TMenuItem;Query1: TQuery;DataSource2: TDataSource;procedure AddMenuClick(Sender: TObject);/点击增加子项菜单procedure RenameMenuClick(Sender: TObject);/点击重命名菜单procedure DeleteMenuClick(Sender: TObje

7、ct); /点击删除该项菜单procedure FormCreate(Sender: TObject);procedure TreeClick(Sender: TObject);private Private declarations public Public declarations procedure LoadTree(treeDB:TDBDataSet);/初始化树procedure UpdateTree(curNode:TTreenode; nodeTxt:string; state:string);/更新树function GetNodeLevel(sFormat,sCode:st

8、ring):integer;/获得节点层数function GetCurrChildNodeMaxMa(curNode:TTreenode):string;/获得当前节点子节点的最大编码function GetCurrentNodeBianma(curNode:TTreenode):string;/获得当前节点的编码procedure UpdateTable(bianma:string; cityname:string ;state:string); /更新数据库end;varForm1: TForm1;CurrentTreeNode: TTreeNode;/ AddChildeTreeNod

9、e: TTreeNode;/ flag:boolean; /用于标识是否需要在重命名树结点时更新数据 implementationuses AddChildUnit,RenameItemUnit;$R *.dfmprocedure TForm1.LoadTree(treeDB:TDBDataSet);/初始化树varcurID,nodeTxt:string;level:integer;mynode:array0.3 of TTreenode;begin /初始化变量Screen.Cursor:=crHourGlass;tree.Enabled:=True;tree.Items.Clear;le

10、vel:=0 ;/设置根节点mynodelevel:=tree.items.add(Tree.Topitem,cTreeRootTxt);mynodelevel.ImageIndex:=1;/遍历数据表,利用编码字段记录排序规律,依次添加树节点with treeDB dobegintryif not Active then open;first;while not Eof dobegincurID:=trim(FieldByName(bianma).AsString);nodeTxt:=curID+-+trim(FieldByName(cityname).AsString);level:=Ge

11、tNodeLevel(cTreeCodeFormat,curID);/这里返回代码的层次数if level0 thenbegin/增加下一节点时,用添加子节点的方法可轻松实现节点间的层次关系/注意:这里的父节点是用当前节点的上一级节点 mynodelevel-1mynodelevel:= tree.items.addchild(mynodelevel-1,nodeTxt);mynodelevel.ImageIndex:=2;end;next;/下一条记录end;finallyclose;End;mynode0.expand(False);Screen.Cursor:=crDefault; en

12、d;end;function TForm1.GetNodeLevel(sFormat,sCode:string):integer;/获得节点层数var i,level,iLen:integer;beginlevel:=-1 ;iLen:=0;if (sFormat ) and (sCode ) thenfor i:=1 to Length(sFormat) do /分析编码格式,找出当前代码层次beginiLen:=iLen+StrToInt(sFormati);if Length(sCode)=iLen thenbegin level:=i; break; end;end;result:=l

13、evel;end;/以下过程在新增、删除、修改记录时,同步更新树形结构procedure TForm1.UpdateTree(curNode:TTreenode; nodeTxt:string; state:string);Beginif UpperCase(state)=ADD thenbegincurNode:=tree.items.addchild(curNode,nodeTxt);curNode.ImageIndex:=2;end;if UpperCase(state)=DEL thenbegincurNode.DeleteChildren;curNode.delete;end;if

14、UpperCase(state)=EDI then curNode.Text:=nodeTxt;end;procedure TForm1.AddMenuClick(Sender: TObject);/点击增加子项菜单var AddChildText, AddTableText,maxbianma : string;beginAddChildForm.Label1.Caption:=为“+CurrentTreeNode.Text+ “增加子项 ;if AddChildForm.ShowModal=mrOk thenbeginAddChildText:=AddChildForm.Edit1.Tex

15、t; maxbianma:=GetCurrChildNodeMaxMa(CurrentTreeNode);if (CurrentTreeNode.Text=城市) and (maxbianma=1000) thenmaxbianma:=11/如果当前节点为根节点,且只有一个子节点,使增加节点编码为11else if CurrentTreeNode.Text=城市 thenmaxbianma:=IntToStr(StrToInt(LeftStr(maxbianma,2)+1)elsemaxbianma:=IntToStr(StrToInt(maxbianma)+1); /使子项编码自动增1if

16、maxbianma 0 thenbegin/增加树子层AddTableText:=maxbianma+-+AddChildText;UpdateTree(CurrentTreeNode,AddTableText,add); /更新树UpdateTable(maxbianma,AddChildText,add); /更新表ShowMessage(添加成功 !);endelse ShowMessage(此层为最低子层,不能在该层增加子层 );AddChildForm.Edit1.Text:=;end;end;function TForm1.GetCurrChildNodeMaxMa(curNode:TTreenode):string;/获得当前节点子节点的最大编码varaSQL,maxbian

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号