采用队列的方式来实现数据库到TTreeView控件上树形结构的构建。(0分)

  • 主题发起人 主题发起人 sky1001
  • 开始时间 开始时间
S

sky1001

Unregistered / Unconfirmed
GUEST, unregistred user!
大家都知道,在很多应用场合,都存在着很多像树一样的结构:如组织结构、物品分类、论坛内容分类等等。由于这些结构是可以无限增加,任意构造的。而这样的很多信息大都是存放在数据库中。因此,把存放在数据库中的树形结构数据实现在TTreeView控件上是很实用的技术。目前网络上大都是采用递归的方式来实现。这里采取一种不同的方式来实现: 即采用队列的方式来实现数据库到TTreeView控件上树形结构的构建。下面是几个要点和代码。<br><br>1. 数据库存放树形的表至少要包含三个字段:<br> &nbsp;<br> &nbsp; &nbsp; &nbsp; NodeId-----------------------自动增量,表的关键字<br> &nbsp; &nbsp; &nbsp; NodeParentId-------------整数<br> &nbsp; &nbsp; &nbsp; Nodename-----------------字符串<br><br>2.把树上每个节点在数据库里的关键字索引NodeId存放在其Data指针里。<br><br>3. 为了实现界面和业务的分离,在树的构建中采取的数据集是TClientDataSet.<br><br>4.没有采用DELPHI自带的TQueue,因为其效率不高。这里使用了一种利用循环数组实现队列的方法。效率比DELPHI自带的TQueue要高。是一种非常实用的队列实现技术。<br><br>实现代码:<br><br>{利用队列实现树形结构}<br>unit DBTreeView;<br><br>interface<br>uses<br> ComCtrls,DBClient,Classes;<br><br><br>Type<br><br> TNodeQueue = class<br> &nbsp;private<br> &nbsp; FCount : integer;<br> &nbsp; FList &nbsp; &nbsp; &nbsp;: TList;<br> &nbsp; FHead &nbsp; : integer;<br> &nbsp; FTail &nbsp; &nbsp; : integer;<br> &nbsp;protected<br> &nbsp; procedure Grow;<br> &nbsp;public<br> &nbsp; constructor Create(aCapacity : integer);<br> &nbsp; destructor Destroy; override;<br> &nbsp; procedure Enqueue(aItem : pointer);<br> &nbsp; function Dequeue : pointer;<br> &nbsp; property Count : integer read FCount;<br> end;<br><br><br> TDBTreeView = class<br> &nbsp;private<br> &nbsp; FTreeView &nbsp; &nbsp; : TTreeView;<br> &nbsp; FcdsTree &nbsp; &nbsp; &nbsp; &nbsp; : TClientDataSet;<br> &nbsp; FQueue &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : TNodeQueue;<br> &nbsp; FRootname &nbsp; &nbsp;: string;<br> &nbsp;public<br> &nbsp; Constructor Create(aTreeView : TTreeView; aRootName : string; cdsTree : TClientDataSet);<br> &nbsp; Destructor Destroy;override;<br> &nbsp; Procedure DrawTree;<br> end;<br><br>implementation<br><br>{------------------------------------------------------------------------------}<br>{--------------------------- TNodeQueue ---------------------------------------}<br>{------------------------------------------------------------------------------}<br>constructor TNodeQueue.Create(aCapacity : integer);<br>begin<br> inherited Create;<br> FList := TList.Create;<br> FCount := 0;<br> FHead &nbsp;:= 0;<br> FTail &nbsp;:= 0;<br> if (aCapacity &lt;= 1) then<br> &nbsp;aCapacity := 16;<br> FList.Count:=aCapacity;<br>end;<br><br>destructor TNodeQueue.Destroy;<br>begin<br> FList.Free;<br> inherited;<br>end;<br><br>procedure TNodeQueue.Grow;<br>var<br> i &nbsp; &nbsp;: integer;<br> Inx &nbsp;: integer;<br>begin<br> FList.Count := (FList.Count * 3) div 2;<br> if (FHead=0) then<br> &nbsp;FTail:=FCount<br> else<br> begin<br> &nbsp;Inx := FList.count;<br> &nbsp;for i:=Pred(FCount) downto FHead do<br> &nbsp;begin<br> &nbsp; Dec(Inx);<br> &nbsp; FList[Inx]:=FList;<br> &nbsp;end;<br> &nbsp;FHead:=Inx;<br> end;<br>end;<br><br>Procedure TNodeQueue.Enqueue(aItem: Pointer);<br>begin<br> FList[FTail]:=aItem;<br> FTail:=(FTail+1) mod FList.Count;<br> inc(FCount);<br> if(FTail=FHead) then<br> &nbsp;Grow;<br>end;<br><br>Function TNodeQueue.Dequeue : pointer;<br>begin<br> if (FCount = 0) then<br> &nbsp;Result:=nil<br> else<br> begin<br> &nbsp;Result:=FList[FHead];<br> &nbsp;FHead:=(FHead+1) mod FList.Count;<br> &nbsp;Dec(FCount);<br> end;<br>end;<br><br>{------------------------------------------------------------------------------}<br>{--------------------------- TDBTreeView --------------------------------------}<br>{------------------------------------------------------------------------------}<br><br>constructor TDBTreeView.Create(aTreeView: TTreeView; aRootName : string; cdsTree : TClientDataSet);<br>begin<br> inherited Create;<br> FTreeView := aTreeView;<br> FRootName := aRootName;<br> FcdsTree &nbsp;:= cdsTree;<br> FQueue &nbsp; &nbsp;:= TNodeQueue.Create(16);<br>end;<br><br>destructor TDBTreeView.Destroy;<br>begin<br> FQueue.Free;<br> inherited;<br>end;<br><br>Procedure TDBTreeView.DrawTree;<br>var<br> Root,TreeNode : TTreeNode;<br> ParentNodeId &nbsp;: integer;<br>begin<br> FTreeView.Items.Clear;<br> Root:=FTreeView.Items.Add(nil,FRootName);<br> parentNodeId := 0;<br> FcdsTree.First;<br> while not FcdsTree.Eof do<br> begin<br> &nbsp;if (FcdsTree.FieldByName('ParentNodeId').AsInteger = ParentNodeId) then<br> &nbsp;begin<br> &nbsp; TreeNode:=FTreeView.Items.AddChild(Root,FcdsTree.fieldbyname('Nodename').AsString);<br> &nbsp; TreeNode.Data := pointer(FcdsTree.FieldByName('NodeId').AsInteger);<br> &nbsp; FQueue.Enqueue(TreeNode);<br> &nbsp; FcdsTree.Next;<br> &nbsp;end<br> &nbsp;else<br> &nbsp;begin<br> &nbsp; Root := TTreeNode(FQueue.Dequeue);<br> &nbsp; if (integer(TTreeNode(Root).Data) = FcdsTree.Fieldbyname('ParentNodeId').AsInteger) then<br> &nbsp; &nbsp;ParentNodeId:=FcdsTree.Fieldbyname('ParentNodeId').AsInteger;<br> &nbsp;end;<br> end;<br>end;<br><br>end.<br><br>测试例子代码<br><br>unit Unit1;<br><br>interface<br><br>uses<br> &nbsp;Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br> &nbsp;Dialogs, ComCtrls, DB, ADODB, DBTables, StdCtrls, Provider, DBClient,DBTreeView,<br> &nbsp;ExtCtrls, DBCtrls, Grids, DBGrids;<br><br>type<br> &nbsp;TForm1 = class(TForm)<br> &nbsp; &nbsp;TreeView1: TTreeView;<br> &nbsp; &nbsp;cdstree: TClientDataSet;<br> &nbsp; &nbsp;DataSetProvider1: TDataSetProvider;<br> &nbsp; &nbsp;ADOConnection1: TADOConnection;<br> &nbsp; &nbsp;ADOQuery1: TADOQuery;<br> &nbsp; &nbsp;Button1: TButton;<br> &nbsp; &nbsp;procedure FormCreate(Sender: TObject);<br> &nbsp; &nbsp;procedure FormDestroy(Sender: TObject);<br> &nbsp; &nbsp;procedure Button1Click(Sender: TObject);<br> &nbsp;private<br> &nbsp; &nbsp;{ Private declarations }<br> &nbsp;public<br> &nbsp; &nbsp;{ Public declarations }<br> &nbsp; &nbsp; DBTree : TDBTreeView;<br> &nbsp;end;<br><br>var<br> &nbsp;Form1: TForm1;<br><br>implementation<br><br><br><br>{$R *.dfm}<br><br>procedure TForm1.FormCreate(Sender: TObject);<br>begin<br> With adoQuery1 do<br> begin<br> &nbsp;close;<br> &nbsp;sql.Clear;<br> &nbsp;sql.Add('select * from tb_tree order by parentNodeId, NodeId');<br> &nbsp;open;<br> end;<br> cdsTree.Active:=true;<br> DBTree := TDBTreeView.Create(TreeView1,'测试',cdsTree);<br>end;<br><br>procedure TForm1.FormDestroy(Sender: TObject);<br>begin<br> DBTree.Free;<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br> DBTree.DrawTree;<br>end;<br><br>end.<br><br><br>第一次发原创技术贴,不完善的地方,多包涵。
 
有现成的代码。。。
 
后退
顶部