难搞,偶搞了几天了。。情况是这样的:1.主窗体有一个Treeview树。
2.这个树要加载无限下级的部门数据。
3.由于要连到远程SQL,网速慢时显示这个主窗口时假死很久。
4.请问,如何改进这个读取的函数才能假死?
5.要实例代码谢了
部门表结构:
did Dname ParentID Leave
----- ------- -------- -----------
01 北京公司0 1
0101 市场部 01 2
010101 信息部 0101 3
02 上海公司0 1
0201 业务部 02 2
0202 售后部 02 2
03 深圳公司0 1
0301 生产部 03 2
0302 实验室 03 2
//读取树部门数据的函数
procedure TMainForm.ReadTree(tnode:TTreeNode;Fvalue: String);
Var
i: integer;
Flist:TStringList;
Flist1:TStringList;
str,s:string;
snode:TTreeNode;
begin
qryTree.close;
qryTree.sql.clear;
qryTree.sql.add('select did,dname,Parentid from depart where isnull(Parentid,'''')='''+Fvalue+''' ');
qryTree.Open;
qryTree.First;
Flist:=TStringList.Create;
Flist1:=TStringList.Create;
while not qryTree.eof do
begin
Flist.Add(trim(qryTree.fieldbyname('dname').asstring));
Flist1.Add(qryTree.fieldbyname('did').asstring);
qryTree.next;
end;
for i:= 0 to flist.Count-1 do
begin
s:=flist1.Strings[i];
str:=flist.Strings[i];
snode:=Treeview1.items.addchild(tnode,str);
ReadTree(snode,s);
end;
flist.free;
flist1.free;
end;
2.这个树要加载无限下级的部门数据。
3.由于要连到远程SQL,网速慢时显示这个主窗口时假死很久。
4.请问,如何改进这个读取的函数才能假死?
5.要实例代码谢了
部门表结构:
did Dname ParentID Leave
----- ------- -------- -----------
01 北京公司0 1
0101 市场部 01 2
010101 信息部 0101 3
02 上海公司0 1
0201 业务部 02 2
0202 售后部 02 2
03 深圳公司0 1
0301 生产部 03 2
0302 实验室 03 2
//读取树部门数据的函数
procedure TMainForm.ReadTree(tnode:TTreeNode;Fvalue: String);
Var
i: integer;
Flist:TStringList;
Flist1:TStringList;
str,s:string;
snode:TTreeNode;
begin
qryTree.close;
qryTree.sql.clear;
qryTree.sql.add('select did,dname,Parentid from depart where isnull(Parentid,'''')='''+Fvalue+''' ');
qryTree.Open;
qryTree.First;
Flist:=TStringList.Create;
Flist1:=TStringList.Create;
while not qryTree.eof do
begin
Flist.Add(trim(qryTree.fieldbyname('dname').asstring));
Flist1.Add(qryTree.fieldbyname('did').asstring);
qryTree.next;
end;
for i:= 0 to flist.Count-1 do
begin
s:=flist1.Strings[i];
str:=flist.Strings[i];
snode:=Treeview1.items.addchild(tnode,str);
ReadTree(snode,s);
end;
flist.free;
flist1.free;
end;
解决方案 »
- cxgrid如何添加一行值。
- 如图所示,dbgrideh的DBGridEh1BuildIndicatorTitleMenu怎么设
- canvas上 画单位为毫米的线 或者微米
- 很简单的一个问题(代码里调用一个控件的触发持行过程)
- BDE 错误!!!!该怎么办??????晕死!!!!!!!!!!高分送出
- varisnull 在什么单元中,在线等?
- 到东京去,我们要血洗这座城市!
- 请大家帮一下,很容易,update 问题
- SynEditor高亮输出
- 我用BDE Administrator 配置完一个.mdb的数据库,当我改table.active为true时
- 如何实现DBGrid滑动条位置的控制?
- delphi 数组游标能否使用字符串
第一次只要显示tree的第一级,在tree的OnExpanded事件中再来显示下级。
把你的query加载数据的过程放到一个线程里就可以了
给你写了个小例子
最好去看看一下多线程的东西
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdFTP, IdBaseComponent, IdComponent, IdTCPConnection,
IdTCPClient, IdHTTP, DB, ADODB, StdCtrls, ActiveX;// 读取数据的线程
type
TReadDataThread = class(TThread)
private
// 线程执行代码
procedure Execute; override;
end;
type
TForm1 = class(TForm)
qryTree: TADOQuery;
Memo1: TMemo;
Button1: TButton;
ADOConnection1: TADOConnection;
procedure Button1Click(Sender: TObject);
private
ReadDataThread: TReadDataThread ;
procedure RdThreadterminate(Sender: TObject);
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}{ TReadDataThread }procedure TReadDataThread.Execute;
begin
inherited;
// 在线程执行代码里写数据的数据读取过程
CoInitialize(nil);
with Form1.qryTree do
begin
sql.Text := 'Select top 1000000 * from groupuserinfo';
Open;
end;
CoUninitialize ;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
// 创建线程,创建为挂起状态
ReadDataThread := TReadDataThread.Create(True);
// 线程结束自动释放
ReadDataThread.FreeOnTerminate := true;
// 线程结束时在主进程调用的方法(通俗说该事件通知主进程线程结束,内容读取完毕)
ReadDataThread.OnTerminate := RdThreadterminate;
// 唤醒线程,使线程开始执行
ReadDataThread.Resume ;
end;procedure TForm1.RdThreadterminate(Sender: TObject);
begin
// 数据库读取结束后显示数据
qryTree.First ;
while not qryTree.Eof do
begin
Memo1.Lines.Add(qrytree.fieldbyname('qqname').AsString);
Application.ProcessMessages ;
qryTree.Next ;
end;
end;end.
(1)取数据时必须按照did排序
(2)循环数据集:
var
ParentNode: TTreeNode;
ChildNode: TTreeNode;
while not Qry.Eof do
begin
case Length(Qry.FieldByName('did').AsString)/2 of
1: //第一级
begin
ParentNode := TreeView1.Nodes.Add(nil, ...);
end;
2: //第二级
begin
ChildNode := TreeView1.Nodes.Add(ParetNode, ...);
end;
3:
begin
ChildNode := TreeView1.Nodes.Add(ChildNode, ...);
end;
4:
begin
ChildNode := TreeView1.Nodes.Add(ChildNode, ...);
end;
...(此处省略)
end;
end;只是思路,没有上级环境,请自己完善之,此法速度最快,事件复杂性为O(n)。
2、如果一定要使用递归,请使用数据集的Filter属性,不要每次调用都去服务器取数据,Filter一下比去服务器取一次数据要快很多的;
其实问题就在于网速。。如果网速够快的话就不会那样。。因为是ADSL外网连到公网上的SQL服务器有没办法,先下载数据集到本地,再计算?现在就是要多次的进行远程连接SQL,速度这样吗?另,Fitter这个属性如何实现这种查询吗?
然后是根据内存里的记录生成树的节点——这个应该不会太慢,如果采用了 TV.Items.BeginUpdate; ... TV.Items.EndUpdate;