如何加快读入tree的数据的速度?(100分)

  • 主题发起人 主题发起人 mayi
  • 开始时间 开始时间
M

mayi

Unregistered / Unconfirmed
GUEST, unregistred user!
我用tree控件显示一个数据库,当数据库很小时,显示速度还可以,但当数据达到1000条
以上时,读入tree时显得很慢。我原来是用递归的方法显示数据的。不知用何种方法可以使
读入tree的速度更快一些。100分!
 
读入前
TreeView1.Items.BeginUpdate
然后读入
读入完后
TreeView1.Items.EndUpdate
 
可以用DoubleWood的方法来加快TreeView的速度,用BeginUpdate和EndUpdate可以控制
TreeView的刷新。如果能再加快数据库的读取速度就更好了。
 
TreeView1.Items.BeginUpdate和TreeView1.Items.EndUpdate这两句我在程序里都用过,
但觉得还是慢。但“良友”在显示数据方面就很快,就算数据库大到5、6M,不知它是怎
么做的,它好象也是用了tree控件,不知它在显示数据方面是如何处理的?请告之,最好
有例子!
 
可能是用VB做的吧!VB里一般的东西都能连接数据库!(不知道VB的TREEVIEW可不可以,很久不用,都忘了)
 
慢到什么程度?
树是可以展开的吗?
“良友”没用过,不知道是什么,
你可以试试这个方法,就是先将第一级读进来,
然后展开时读第二级。

procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
aNOde: TTreeNode;
begin
TreeView1.Items.BeginUpdate;
for i:= 1 to 100 do
begin
aNOde := TreeView1.Items.AddChild(nil, IntToStr(i));
aNOde.Data := Pointer(1); //做个标记,第二级数据是否已经读入
aNOde.HasChildren := true;
end;
TreeView1.Items.EndUpdate;
end;

procedure TForm1.TreeView1Expanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
var
i: Integer;
begin
if Node.Data<>nil then //没有读入,则读入
begin
TreeView1.Items.BeginUpdate;
Node.Data:=nil; //做个标记,第二级数据已经读入
NOde.DeleteChildren;
for i:= 1 to 100 do
TreeView1.Items.AddChild(NOde, IntToStr(i));
TreeView1.Items.EndUpdate;
end;
end;

总共10000笔,但是你感觉不到任何延迟,因为把要花的时间分散

 
哈哈,我遇到过同样的问题,不过不是向树里面写,而是从树里面读
那棵tree 是 12x8x16x8 个node
用TreeView 遍历,等死你。
后来我是这么结决的。
TreeView.SavetoStream;
我分析了stream 里各级node 的表示标志,很简单,你一看就知道。
然后可以快速拆分,得到结果,很快,比访问树要快百倍,决不夸张。
而你的问题是写入,就可以更简单了,因为少了分析定位过程。
写完stream 后,stream.position:=0;
TreeView.LoadFromStream, 到手了。

有没有兴趣?


 
请问CGCAT:
我那棵树有四层,我控制每层都是在展开时才从表中读入,而且这棵树每层都可以增删改,
那刷新也要控制只刷新更新的部分,但是我控制的不是很理想,你这种方法可以更好的解决
我这个问题吗
如果可以,我送100分给你
 
to GGCAT:
请您说详细一些,好吗?TreeView.SavetoStream如何使用?能给个例子吗?最好是读取数据库
到tree的例子!如果OK的话,再送分给您!
 
下面的程序只是一个测试,表明该方法的速度,具体的写入数据请自行
解决。(可能只兼容 D5) 在我的计算机上 C333/64M 生成 8x8x8x8的
树并完全加载不到 1s. 不过超过 几 万条记录时不太理想。但是可以
拆分成几个 不到 5000 条的子树载入并合并,性能可以满足要求.

Procedure TForm1.Button1Click(Sender: TObject);
Var ST:TMemoryStream;
LA,LB,LC,LD:Integer;
SA,SB,SC,SD:String;
CA,CB,CC,CD:String;
Max:Integer;
begin
Max:=7; //将生成 7x7x7x7 的树.
ST:=TmemoryStream.Create; //建立内存流
SA:=Chr($0D)+Chr($0A); //各级节点标志
SB:=SA+Chr($09);
SC:=SB+Chr($09);
SD:=SC+Chr($09);
For LA:=1 to Max DO
Begin
CA:='Root '+Inttostr(LA); //根节点内容
ST.Write(PChar(CA)^, Length(CA)); //写入根节点
For LB:=1 to Max DO
Begin
CB:='LevelII '+Inttostr(LB); //次级节点内容
ST.Write(PChar(SB)^, Length(SB)); //写入次级标志
ST.Write(PChar(CB)^, Length(CB)); //写入次级内容 下同,略
For LC:=1 to Max Do
Begin
CC:='LevelIII '+Inttostr(LC);
ST.Write(PChar(SC)^, Length(SC));
ST.Write(PChar(CC)^, Length(CC));
For LD:=1 to Max do
Begin
CD:='Node '+Inttostr(LD);
ST.Write(PChar(SD)^, Length(SD));
ST.Write(PChar(CD)^, Length(CD));
End;
End;
End;
ST.Write(PChar(SA)^, Length(SA)); //写入根节点标志
End;
ST.Position:=0;
TreeView1.LoadFromStream(ST); //从流中载入
ST.Free;
End;
 
GGCAT,
请教,如果要给每个NODE加IMAGE,不知道是否也可以先写到STREAM里?该如何写?
 
没试验过。
不过:
你不妨自己把一个简单的 TreeView 存入 TfileStream 中,再用
hexedit 之类的工具打开分析啊。或者直接看 TCustomTreeView 中
相关方法的source code,对水平的提高很有帮助哦。
 
GGCAT兄,我找了搜了HEXEDIT,但一下载就出错!:(
不知你可否发一分给我!先谢了!!
<A
href="mailto:gcqmail@sohu.com">gcqmail@sohu.com</A>
 
mayi:如果还想接着讨论请定期提前自己的帖子,如果不想继续讨论请结束帖子。
 
你试试在开始处添加api:lockwindowupdate来禁止对该tree控件的刷新,
结尾处取消对该tree控件的刷新禁止,效果如何?
 
谈个想法
1.分层读入,用后台线程。
2.如在点击某一节点时,后台线程尚未读入这一层,则
优先读入此节点下一层的数据,并做一标记。
 
多人接受答案了。
 
后退
顶部