从数据库读取数据动态生成Treeview(100分)

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

sushicheng

Unregistered / Unconfirmed
GUEST, unregistred user!
我用递归法生成Treeview节点.但需要1分多钟.请问高手该如何处理.相信各位
肯定遇到过同样的问题.Access数据库.记录有4000条.很急.老板已经催几次了.
他看过久其的产品.人家只需3,4秒.分全部捧上.
代码如下:
procedure TJdhzFrm.InitArray(var arr: TArr);//放入数组.
var
i:integer;
sql:string;
begin
Query.Close;
Query.SQL.Clear;
Query.SQL.Add('select * from dwqkb');
Query.Open;
Query.First;
SetLength(arr,Query.RecordCount);
i:=0;
while not Query.Eof do
begin
arr.id:=Query.fieldbyname('dwtydm').AsString;
arr.preId:=Query.fieldbyname('dm1').AsString;//.Fields[1].AsString;
arr.Dwmc:=Query.fieldbyname('dwmc').AsString;
Inc(i);
Query.Next;
end;

end;
procedure TJdhzFrm.CreateTree(var arr: TArr);
var
p:pTNodeInfo;
procedure CreateTree(Pre:PTNodeInfo;preNode:TTreeNode;var arr:TArr);
var
pInfo:pTNodeInfo;
node:TTreeNode;
i:integer;
begin
i:=length(arr)-1;
while i>=0 do
begin
new(pInfo);
pInfo:=@arr;
if pInfo.preId=pre.id then
begin
node:=treeview1.Items.AddChild(preNode,pInfo.id+'|'+pInfo.Dwmc);
node.Data:=pInfo;
CreateTree(pInfo,node,arr);
end;
i:=i-1;
end;
end;
begin
new(p);
p.id:=s;
createTree(p,nil,arr);
treeview1.FullExpand;
end;
procedure TJdhzFrm.Button1Click(Sender: TObject);//
var
arr:Tarr;
begin
Initarray(arr);
treeview1.Items.BeginUpdate;
CreateTree(arr);
treeview1.Items.EndUpdate;
end;
 
先生成树型文本文件TXT,然后treeview1.loadfromfile(filename),速度会快很多.不信可以试试
 
你的数要长那么多叶子么
如果不要,换个方法吧,把检索的工作尽量留给数据库引擎来做比较经济
 
树在不断更新.用文本不行啊.
 
看你的代码,是先将数据加载到一动态数组中,而后再依据此数组来构建树。这无形中就多出一次循环。
如果楼主用的是Access数据库,建议在遍历数据集的时候构建树;如果使用的是SQL数据库,则建议利用存储过程将表中的数据依其所在结点层次排好序(第一层结点记录最靠前,其次是第二层,第三层....)这样遍历数据集构建树会更快一些。
 
学习啊
会的说的详细些啊!
 
需要一次全显示出来吗?
否的话,只显示一层目录,展开时再添加字节点onexpanding
 
用递归查询,当然慢了,比较好方法是,一次查到树所有节点信息,一次生成整个树,
呵呵 就看你的功底了。
 
没必要一次性加载,可以延迟加载子节点,当用户选中该节点再加载子节点,我的方法是再node的data属性中保存一个是否已经加载子节点的标志,初始化false,在tree的change事件中判断标志进行加载!
 
帮你顶,Treeview是Delphi关键的控件,我也很想研究一下。
 
谢谢各位的赐教。不过这里必须一次显示。 因为我要做汇总。而且很灵活。选中任一节点。要把他的所有子节点的相关数据全部汇总。不显示做不到这一点啊。
 
呵呵.我的结构是快.我用的dbtreeviewlist控件.直接就可以建结构了。 表就 id 上级id name 就可以了.
但是我的统计出问题.很麻烦呢.我要分级统计.要让用户可以定义统计到第几级.
哪个做过最好给我个例子.很谢谢啊.
 
错了是dxDBTreeView
 
太慢是否索引没建好?
下面是一个使用 过滤的例子
procedure LoadBookToTV(AdoConn:TAdoConnection;tv :TTreeView);
var
AdoQuery :TAdoQuery;

procedure AddChildNode(ANode:TTreeNode);
begin
with AdoQuery do
begin
while ANode <> nil do
begin
Filter := 'FParentID=' + IntToStr(Integer(ANode.StateIndex));
Filtered := True;
if Not Eof then // HasChild
begin
ANode.ImageIndex :=0; // 有子,文件夹图标
ANode.SelectedIndex :=1; // 选择,打开文件夹
while Not Eof do
begin
with tv.Items.AddChild(ANode,FieldByName('FCaption').AsString) do
begin
Data := Pointer(ANode.StateIndex);
StateIndex := FieldbyName('FID').AsInteger;
//ToDo: Check Extend
ImageIndex := GetImageIndexFormExtend(
LowerCase(Trim(FieldbyName('FExtend').AsString)));
SelectedIndex := ImageIndex;
end;
Next;
end;
AddchildNode(ANode.getFirstChild); // 递归 - 使用当前节点下第一个子节点
end;
ANode := ANode.getNextSibling ; // 取同级下一节点
end;
end;
end;
begin
tv.Items.Clear;
AdoQuery := TAdoQuery.Create(nil);
try
AdoQuery.Connection := AdoConn;
AdoQuery.Sql.Text := 'select FID,FParentID,FCaption,FExtend from T_BOOK order by FParentID,FSeq';
AdoQuery.Open;
if AdoQuery.RecordCount<1 then Exit;

AdoQuery.Filter := 'FParentID=0'; // 1.先加顶层节点
AdoQuery.Filtered := True;
while Not AdoQuery.Eof do
begin
with tv.Items.Add(nil,AdoQuery.FieldByName('FCaption').AsString) do
begin
Data := Pointer(0);
StateIndex := AdoQuery.FieldbyName('FID').AsInteger;
//ToDo: Check Extend
ImageIndex := GetImageIndexFormExtend(
LowerCase(Trim(AdoQuery.FieldbyName('FExtend').AsString))); // 根据后缀名确定显示图标
SelectedIndex := ImageIndex;
end;
AdoQuery.Next;
end;
AddChildNode(tv.Items.GetFirstNode); // 2.递归加入子节点
AdoQuery.Close;
finally
AdoQuery.Free;
end;
end;
 
//递归的
procedure AddClass(AId: string;FatherNode:TTreeNode);
var
myLabel:TLabel;
i:integer;
begin
with StringGrid do
begin
for i:=0 to RowCount-1 do
begin
if Cells[2,i]=AID then //Cells[2,i]上级节点
begin
myNode:=Treeview1.Items.AddChild(FatherNode,Cells[1,i]);//Cells[1,i]名称
myLabel:=TLabel.Create(self);
myLabel.Visible:=true;
myLabel.Caption:=Cells[0,i];//Cells[0,i]编号
myNode.Data:=myLabel;
AddClass(Cells[0,i],myNode); //递归调用
end;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
AddClass('0',nil);
end;
 
后退
顶部