■■■■■■■关于treeview逐级展开的问题!(200分)

  • 主题发起人 主题发起人 dugucan
  • 开始时间 开始时间
D

dugucan

Unregistered / Unconfirmed
GUEST, unregistred user!
我用treeview+accesss写的个程序,treeview分很多级,每级上都有N多个节点,算下来有6000多个,但是现在问题出来了,程序打开时,加载这个树要N长时间,肯定不行。

我想逐级展开这个树,也就是开始只加载一级或者两级结节,点击后判断还有没有子节点,有的话就展开,没有的话就执行命令,查了很多贴子,都不行,因为每个人的数据表结构都不一样,一般都只发一段代码,还是搞不清楚,我想要个例子,代码加数据表结构的,能不能给一个,马上给分,或者我把表结构贴在下面,大家给段简单的代码也行。表如下:

ID NAME SJBH(表示结点关系的标记) ZL(点击结点后显示出的资料)
1 一年级 0 及格
2 二年级 0 及格
3 张三 1 不及格
4 李四 1 极格
5 王五 2 不及格


SJBH的意思就是根据前面的ID显示,如果SJBH是0,就是最上一级,SJBH是1的话,就为在ID为1的子结点,SJBH为2的话就是ID为2的子结点。。。。。。


我觉得这个表的结构也不怎么样,最好能有个简单的代码加表结构的例子看一看
dugucan8000@163.com
如果方便的话,请帮一下忙,我非常的急!
■■■最好能给一个实例到我邮箱里,我是新手■■■■
 
//自定义过程展现treeview中内容
procedure TfrmSmoke.Display_Treeview();
var
Root_Node,Child_Node,ChildSmoke_Node : TTreeNode; //临时根节点、子节点
begin
TreeView.Items.Clear;
//展现省份信息
Query_Province.Close;
Query_Province.SQL.Clear;
Query_Province.SQL.Add('Select Distinct ID,Value From Dictionary Where Type=1');
Query_Province.Open;
while not Query_Province.Eof do
begin
Root_Node:=TreeView.Items.AddFirst(nil,Trim(Query_Province.FieldByName('Value').AsString));
//展现每个省份下面对应的烟厂信息
Query_Manufactory.Close;
Query_Manufactory.SQL.Clear;
Query_Manufactory.SQL.Add('Select M_ID,M_Name From Manufacturer Where M_Province='+ Query_Province.FieldByName('ID').AsString);
Query_Manufactory.Open;
while not Query_Manufactory.Eof do
begin
Child_Node:=TreeView.Items.AddChild(Root_Node,Trim(Query_Manufactory.FieldByName('M_Name').AsString));
Query_Smoke.Close;
Query_Smoke.SQL.Clear;
Query_Smoke.sql.Add('Select * From Goods Where I_Manufacturer=' + trim(Query_Manufactory.FieldByName('M_ID').AsString));
Query_Smoke.Open;
while not Query_Smoke.Eof do
begin
ChildSmoke_Node :=TreeView.Items.AddChild(Child_Node,Trim(Query_Smoke.FieldByName('I_ID').AsString)+'--'+Trim(Query_Smoke.FieldByName('I_Name').AsString));
Query_Smoke.Next;
end;
Query_Manufactory.Next;
end;
Query_Province.Next;
end;
Query_Province.Close;
Query_Manufactory.close;
Query_Smoke.Close;
end;

//在TreeView中显示所有省份信息。
procedure TfrmSmoke.FormShow(Sender: TObject);
begin
Display_Treeview(); //显示数据库中所有的卷烟信息
end;

//单击“卷烟名称”,显示卷烟信息。
procedure TfrmSmoke.TreeViewClick(Sender: TObject);
begin
if TreeView.Items.Count <=0 then Abort;
Query_Smoke.Close;
Query_Smoke.SQL.Clear;
Query_Smoke.SQL.Add('Select * From Goods Where I_ID='''+LeftStr(TreeView.Selected.Text,Pos('--',TreeView.Selected.Text)-1)+''' ');
Query_Smoke.Open;
Edt_ID.Text :=Query_Smoke.FieldByName('I_ID').AsString;
Edt_Name.Text :=Query_Smoke.FieldByName('I_Name').AsString;
Edt_Price.Text :=Query_Smoke.FieldByName('I_Price').AsString;
Edt_BarCode.Text :=Query_Smoke.FieldByName('I_BarCode').AsString;
Edt_Box.Text :=Query_Smoke.FieldByName('I_Box').AsString;
Edt_Piece.Text :=Query_Smoke.FieldByName('I_Piece').AsString;
Edt_Bag.Text :=Query_Smoke.FieldByName('I_Bag').AsString;
Edt_Min.Text :=Query_Smoke.FieldByName('I_UpperLimit').AsString;
Edt_Max.Text :=Query_Smoke.FieldByName('I_LowerLimit').AsString;
Edt_Term.Text :=Query_Smoke.FieldByName('I_Term').AsString;
//显示当前卷烟的存储类别
ComBox_Grade.Style :=csDropDown;
ComBox_Grade.Text :=Query_Smoke.FieldByName('I_Grade').AsString;
{Query_tmp.Close;
Query_tmp.SQL.Clear;
Query_tmp.SQL.Add('Select ID,Value From Dictionary Where ID='''+Query_Smoke.FieldByName('I_Grade').AsString+''' ');
Query_tmp.Open;
ComBox_Grade.Style :=csDropDown;
ComBox_Grade.Text :=Query_tmp.FieldByName('Value').AsString;
}
//显示当前卷烟的级别
Query_tmp.Close;
Query_tmp.SQL.Clear;
Query_tmp.SQL.Add('Select ID,Value From Dictionary Where ID='''+Query_Smoke.FieldByName('I_Class').AsString+''' ');
Query_tmp.Open;
ComBox_Class.Style :=csDropDown;
ComBox_Class.Text :=Query_tmp.FieldByName('Value').AsString;
//存在卷烟即可以修改,否则不能修改。
if Length(Edt_ID.Text) >0 then
begin
Bu_Edit.Enabled :=true; //可以修改卷烟信息
end;
end;
 
在程序开始时,搜索整个表,将pid是0的记录作用一级节点加到TreeView的中,并将每条记录的sid 保存在对应的data属性中(Node.Data := Pointer(Table.FieldByName('sid').AsInteger)),然后将这个节点的 HasChildner 设成 True(在具体的应用中,可以设计一种验证方法来判断此条记录是否有子记录,再以此来是否将这个节点的HasChildner 设成 True)。

接下来就是在每个节点的 onExpanding 事件中,以此节点的DATA属性,也就是对应记录的sid值来搜索表中 pid 等于这个值的记录加到这个节点中做为下级节点。

procedure ScanRecForm(const aPid: integer; PNode: TreeNode);
begin
Table.First
while not Table.EOF do
begin
if Table.FieldByName('pid').AsInteger = aPid then
begin
with TreeView.Items.AddChild((PNode, Table.FieldByName('name').AsString) do
begin
Data := Pointer(Table.FieldByName('sid').AsInteger);
.......................................................
end;
........................................
end;
next;
end;
end;

procedure TreeView.OnExpanding(sender: TObject; Node: TTreeNode);
begin
if Node = nil then exit;
ScanRecForm(Integer(Node.data), Node);
end;

以上只是一个实现的例程,具体操作中还有很多细节要根椐环境不同要加以不同方式处理!
 
各位好,谢谢大家回复,我不知道你们表的结构,只有一段代码,而且DELPHI的基础并不是很好,我看了好长时间,意思明白了一些,但是还是不能完全搞懂,能给个最基础的rar的例子吗?我在网上搜不到,比较急
 
给你的邮件地址,发一个给你,你修改了使用就好。可以保证你的速度。
 
dugucan@yeah.net
或者dugucan8000@163.com
谢谢了
 
已经发出。
 
晕,这是用的什么数据库啊,还有控件,我试试,可以的话就把贴子结了,如果还有谁有例子的话也发份过来,我另开贴给分
 
是不是差数据库文件啊,zywcd
 
每个节点里加个指针就行了。这个技术在远程取对方电脑文件夹很关键。不能一次都取。否则很慢。只能先进取C、D、E盘等。点击什么取什么。就是靠指针的
 
装了两件控件,终于可以用了,你上面说的就是分级读取树的意思了,我来想办法改一改这个树用,我只要这一点东西,好复杂啊,估计工作量够大的,还有,只能远程取??我取的是我的ACCESS数据库上的内容
 
忘了问你,他这个填加节点的数据到底是保存在哪里面啊zlgl.dat是个什么文件,用什么打开啊
 
你用一个递归算法就行了,在选择的节点上来调用该函数,或循环加载数据库的内容,最好是用指针来实现,因为你有加载还要有删除与修改
 
晕,就是因为递归或者循环加载数据库的内容速度慢啊,6000多个节点

我的想法是把这个树先建好,按他的方法来读取树,只读第一级,点击某节点后加载他的子节点,如果没有子节点就执行这个节点的操作,但是他这个树的数据到底保存在哪里,是zlgl.dat文件里吗?用什么打开??
 
还是觉得太复杂了,大家还有没有别的例子啊????
treeview+access,最基础的例子
 
简单啦。很早前就做过。
你可以在FORM SHOW过程,先展开两层。
在数据库中读数据进行加载。
lssql:='select type,memo,code from h_forgoods where pcode=0 ';
ADOQtemp.Close;
ADOQtemp.SQL.Clear;
ADOQtemp.SQL.Add(lssql);
ADOQtemp.Open;
ADOQtemp.First;
thisnode:=TreeView1.Items.GetFirstNode;
thisnode.DeleteChildren;
while not(ADOQtemp.Eof) do
begin
lstype:=Trim(ADOQtemp.FieldByName('type').AsString);
lsmemo:=Trim(ADOQtemp.FieldByName('memo').AsString);
thisnode:=TreeView1.Items.Addchild(thisnode,lsType);
lssql:='select type,memo from h_forgoods where pcode='''+lscode+'''';
ADOQtempx.Close;
ADOQtempx.SQL.Clear;
ADOQtempx.SQL.Add(lssql);
ADOQtempx.Open;
ADOQtempx.First;
while not ADOQtempx.Eof do
begin
lstype:=Trim(ADOQtempx.FieldByName('type').AsString);
lsmemo:=Trim(ADOQtempx.FieldByName('memo').AsString);
TreeView1.Items.Addchild(thisnode,lsType);
ADOQtempx.Next;
end;
thisnode:=TreeView1.Items.GetFirstNode;
thisnode.Expand(False);
TreeView1.Refresh;
ADOQtemp.Next;
end;
Application.ProcessMessages;
在TREEVIEW的ONExpanding,再进行数据读取,就搞定。
 
反正你只要有了父子结点就可以挂树了 随便你怎么挂``
你想要什么样的 用友是先挂一级 然后你点击结点的时候再去查有没有下级 有下级就加上一临时结点 展开时在删除这个结点下的所有结点 重新加载该结点下的子结点``
 
多人接受答案了。
 
后退
顶部