表DeptInfo:
Code SubCode (字段)
A C
A E
B D
B F
C G
D H 其中,Code是SubCode的上级部门。 上述表用TREEVIEW显示如下:
___
A--| C--G
| |___ E
|
B--|-- D-H
|
---- F 请问用什么算法让数据更快更好的加载到TREEVIEW来呢?
100分相送,决不食言!!!
(有代码最好!)
Code SubCode (字段)
A C
A E
B D
B F
C G
D H 其中,Code是SubCode的上级部门。 上述表用TREEVIEW显示如下:
___
A--| C--G
| |___ E
|
B--|-- D-H
|
---- F 请问用什么算法让数据更快更好的加载到TREEVIEW来呢?
100分相送,决不食言!!!
(有代码最好!)
解决方案 »
- 打开某个exe应用程序,怎么点击里面的控件 ?
- 求16进制字符串转数值的函数
- 使用mssql时能不能像oracle一样,连接服务器仅使用客户端,应用程序只跟客户端发生数据交换?
- Paradox数据库不稳定吗?为什么会异常清空?
- 怎样做一个有颜色的菜单?
- 我在工程文件中uses midasLib单元,将midas打包进服务器端,exe也大了200多K,但运行时为什么还是提示需要midas.dll?应该怎么做才能编译成
- "网络蚂蚁"和"FlashGet"的悬浮窗口的实现
- 用 ListView 做类似 flashget 下载图表那个小圆球的东西,遇到一些问题。。。。。。。。。。。。
- 输入word文档viso文档和excel文档。要求输出的结果是pdf文档,如何实现?
- 如何在delphi中使用DirectX?
- 遇到一个问题:数组怎么开辟到512*512?
- 请教,一个COMBOBOX,里面有文本提供用户选择,比如广州,我要用一条SQL写成SELECT * FROM A WHERE B= COMBOBOX。TEXT
可是我发觉陷入一个递归陷阱,光是一级一级找部门级别层次都很累了
如何解决这个问题呢?
先用一个RootQry:TADOQuery来取第一级部门SQL象这样
select * from DepInfo where not code in (select SubCode from DepInfo)
用一个DetailQry:TADOQuery来Select * from DepInfo然后再用递归生成树---绝对累不死CPU,除非你程序有死循环!也不应该很慢!!大体如下:
var
ANode:TTreeNode;
begin
RootQry.First;
while not RootQry.Eof do
begin
ANode:=TreeView.Items.Add(nil,RootQry.FieldByName('Code').AsString);
CreateChild(ANode);
RootQry.Next;
end;
procedure CreateChild(FNode:TTreeNode);
var
BookMark:String;
ANode:TTreeNode;
begin
DetailQry.First;
While Not DetailQry.Eof do
begin
if DetailQry.FieldByName('Code').AsString=FNode.Text then
begin
ANode:=TreeView.Items.AddChild(FNode,
DetailQry.FieldByName('SubCode').AsString);
Book:=DetailQry.Book;
CreateChild(ANode);//此处递归!!
DetailQry.Book:=Book;
end;
DetailQry.Next;
end;
DetailQry.
end;
procedure InitTreeView(TreeNode:TTreeNode;Key:String);
var
TN:TTreeNode;
s_ADOQuery:TADOQuery;
begin
s_ADOQuery:=TADOQuery.Create(self);
s_ADOQuery.Connection:=ADOConnection1;
s_ADOQuery.Close;
s_ADOQuery.SQL.Clear;
s_ADOQuery.SQL.Text:='select code,subcode from deptinfo where code='+Quotedstr(key);
s_ADOQuery.Open;
if not s_ADOQuery.IsEmpty then
begin
while not s_ADOQuery.Eof do
begin
TN:=Treeview1.Items.AddChild(TreeNode,s_ADOQuery.fieldbyname('subcode').AsString);
InitTreeView(TN,s_ADOQuery.fieldbyname('subcode').AsString);
s_ADOQuery.Next;
end;
end;
end;procedure TForm1.Button1Click(Sender: TOBject);
begin
InitTreeView(nil,'0');
end;
var i,j:integer;
begin
result:=nil;
j:=treeview.Items.Count;
for i:=0 to j-1 do
begin
if treeview.Items[i].Text=text then
begin
result:=treeview.Items[i];
exit;
end;
end;
end;procedure TForm1.MoveChildNode(TreeView:TTreeView;DestNode:TTreeNode;SourNode:TTreeNode);
var tn1,tn2:TTreeNode;
begin
tn1:=nil;
tn2:=nil;
tn1:=sournode.getFirstChild;
if tn1<>nil then
begin
tn2:=treeview.Items.AddChild(destnode,tn1.Text);
if tn1.HasChildren then
begin
self.MoveChildNode(treeview,tn2,tn1);
end;
end;
tn1:=sournode.GetNextChild(tn1);
while tn1<>nil do
begin
tn2:=treeview.Items.AddChild(destnode,tn1.Text);
if tn1.HasChildren then
begin
self.MoveChildNode(treeview,tn2,tn1);
end;
tn1:=sournode.GetNextChild(tn1);
end;
tn1:=nil;
tn2:=nil;
end;procedure TForm1.Button1Click(Sender: TObject);
var tn1,tn2,tn3:TTreeNode;i,j:integer;value:string;
begin
table1.Open;
while not table1.Eof do
begin
value:=table1.FieldValues['code'];
tn1:=self.FindNode(self.TreeView1,value);
if tn1=nil then
begin
tn1:=self.TreeView1.Items.Add(nil,value);
end;
value:=table1.FieldValues['subcode'];
tn2:=self.FindNode(self.TreeView1,value);
if tn2=nil then
begin
tn2:=self.TreeView1.Items.AddChild(tn1,value);
end else
begin
tn3:=self.TreeView1.Items.AddChild(tn1,value);
self.MoveChildNode(self.TreeView1,tn3,tn2);
tn2.Delete;
end;
table1.Next;
end;
table1.Close;
end;
var
m:TTreeNode;
s_ADOQuery:TADOQuery;
begin
s_ADOQuery:=TADOQuery.Create(self);
s_ADOQuery.Connection:=ADOConnection1;
s_ADOQuery.Close;
s_ADOQuery.SQL.Clear;
s_ADOQuery.SQL.Text:='select distinct(code) from deptinfo where code not in (select distinct(subcode) from deptinfo)';
s_ADOQuery.Open;
if not s_ADOQuery.IsEmpty then
begin
while not s_ADOQuery.Eof do
begin
m:=TreeView1.Items.Add(nil,s_ADOQuery.fieldbyname('code').AsString);
InitTreeView(m,s_ADOQuery.fieldbyname('code').AsString);
s_ADOQuery.Next;
end;
end;
end;
不过你的算法出现一个问题,上述数据中,上级代码A出现了两次,B也如此。
还有C和D也在A和B的同一级。
的方法主要在query的指针移动上消耗时间我的方法主要在移动node上消耗时间: bluezwt(蓝色天涯)
的方法主要是增加了数据库的连接数量楼主 你都试试看哪个方法快?
你的建议我已经接受了!
不过你的方法我好像陷入死循环。
不过你的方法我也好像陷入死循环。
blazingfire(烈焰)(正在思考的流浪汉...)的算法快。
在query的指针移动上消耗时间;肯定要比移动节点上消耗时间少。
如有不妥请斧正!
[email protected]
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,ComCtrls, DB,StdCtrls;type TTreeNodeInfo=record
Id:String;
ParentId:String;
end; TDBTreeView=class(TTreeView)
private
fTable:TDataSet;
fId,fParentId,fName:string;
function AddItem:TTreeNode;
function FindItem(Id:string):TTreeNode;
protected
procedure Change(Node: TTreeNode); override;
public
function GetId:string;
procedure BuildTree;
procedure ClearTree; constructor Create(AOwner:TComponent);override;
destructor Destroy;override;
published
property FieldId:string Read fId Write fId;
property FieldParentId:string Read fParentId Write fParentId;
property FieldName:string Read fName Write fName;
property DataSource:TDataSet Read fTable Write fTable;
property ActiveId:string Read GetId;
end;
procedure Register;implementationfunction TDBTreeView.FindItem(Id:string):TTreeNode;
var i:integer;
NodeInfo:^TTreeNodeInfo;
begin
Result:=nil;
For i:=0 to Items.Count-1 do
begin
NodeInfo:=Items[i].Data;
If NodeInfo^.Id=Id then
begin
Result:=Items[i];
Exit;
end;
end;
end;function TDBTreeView.GetId:string;
var NodeInfo:^TTreeNodeInfo;
begin
If Selected=nil then Result:=''
else
begin
NodeInfo:=Selected.Data;
Result:=NodeInfo^.Id;
end;
end;function TDBTreeView.AddItem:TTreeNode;
var NodeInfo:^TTreeNodeInfo;
BMark:TBookMark;
ObjParent:TTreeNode;
Name,CurId:string;
begin
ObjParent:=FindItem(fTable.FieldByName(fId).AsString);
If ObjParent<>nil then
begin
Result:=ObjParent;
Exit;
end
else
begin
New(NodeInfo);
NodeInfo^.Id:=fTable.FieldByName(fId).AsString;
NodeInfo^.ParentId:=fTable.FieldByName(fParentId).AsString;
Name:=fTable.FieldByName(fName).AsString;
If fTable.FieldByName(fParentId).AsString<>'' then
begin
ObjParent:=FindItem(Name);
If ObjParent<>nil then
Result:=Items.AddChildObject(ObjParent,Name,NodeInfo)
else
begin
CurId:=fTable.FieldByName(fId).AsString;
If fTable.Locate(fId,fTable.FieldByName(fParentId).AsString,[]) then
begin
Result:=Items.AddChildObject(AddItem,Name,NodeInfo);
fTable.Locate(fId,CurId,[]);
end
else
Result:=Items.AddObject(Selected,Name,NodeInfo);
end;
end
else
begin
Result:=Items.AddObject(Selected,Name,NodeInfo);
end;
end;
end;procedure TDBTreeView.BuildTree;
var ChangeEvent:TTVChangedEvent;
begin
If (fTable=nil) or (not fTable.Active) then Exit;
ChangeEvent:=OnChange;
OnChange:=nil;
Items.BeginUpdate;
ClearTree;
fTable.First;
While not fTable.Eof do
begin
AddItem;
fTable.Next;
end;
AlphaSort;
Items.EndUpdate;
OnChange:=ChangeEvent;
end;procedure TDBTreeView.ClearTree;
var NodeInfo:^TTreeNodeInfo;
i:integer;
begin
Items.BeginUpdate;
for i:=0 to Items.Count-1 do
begin
NodeInfo:=items[i].Data;
Dispose(NodeInfo);
end;
While Items.Count>0 do Items.Delete(Items[0]);
Items.EndUpdate;
end;procedure Register;
begin
RegisterComponents('Data Controls',[TDBTreeView]);
end;constructor TDBTreeView.Create(AOwner: TComponent);
begin
inherited;
end;destructor TDBTreeView.Destroy;
begin
inherited;
end;
end.
var mLocalName: string;
TreeNode: TTreeNode;
Ads_Tmp: TADODataSet;
begin
ADS_Tmp := TADODataSet.Create(Self);
ADS_Tmp.Connection := ADOConn;
with ADS_Tmp do
begin
Close;
CommandText := 'Select * from Type Where ParentID =' + FNodeName;
Open;
First;
while not Eof do
begin
mLocalName := FieldbyName('ID').Asstring;
TreeNode := TreeView.Items.AddChild(Node, FieldByName('Name').AsString);
CreateSubTree(mLocalName, TreeNode);
Next;
end;
end;
end;简单的底归!
ADS_Tmp := TADODataSet.Create(Self);
ADS_Tmp.Connection := ADOConn;
Code parentCode (字段)
001
002 001
003 001
004 002
005 003
006 004
如果用oracle,可以:Select *,level from DeptInfo start with parentCode is null
connect by code=parentCode order by code;
^^^^^^^^^^^^^^//可选
查出:
Code parentCode level
001 1
002 001 2
004 002 3
006 004 4
003 001 2
005 003 3这就是TreeView中的顺序!遍历一边记录,就可以创建所有节点的。
(level是虚拟列,自动赋值的,可以不用)