3,从数据库中读数据生成一棵树,采用什么方法好呢?
请大家指点。有代码最好不过,谢谢!
上面wdsimon(老王) 仁兄的方法没试过,不过我觉得代码量太多,还有递归!,下面的代码大家觉得如何??:
procedure Tcpya_app.FormCreate(Sender: TObject);//窗体初始化时,加载树。
begin
datamodule2.tree.close; //tree:是数据模块中的adoquery
datamodule2.tree.sql.clear;
datamodule2.tree.sql.add('select name from plat order by name');//按照name排序。
datamodule2.tree.Active:=true;
datamodule2.tree.Open;
while not datamodule2.tree.Eof do//填充树
begin
with tv.Items do//增加节点
begin
MyTreeNode1 := Add(nil,trim(datamodule2.tree.fields[0].asstring));//自动增加父节点
with datamodule2 do
begin
child.close;//child是数据模块中的adoquery
child.SQL.Clear;
child.SQL.Add('select comp from dalei where plat='''+Trim(datamodule2.tree.Fields[0].asstring)+''''+' order by comp');
child.Active:=true;
child.Open;
While Not child.Eof do
begin
TV.Items.AddChild(mytreenode1,trim(child.Fields[0].AsString));//在父节点下加子节点
child.Next;
end; end;
datamodule2.tree.Next;
end;
end;
end;
上面的程序中生成父节点的表可以说是主表吧,声称子节点的表是从表,
其中两个表通过plat字段相关联,
2、写一生成树的函数,注意递归:
function TForm1.ShowTree(TNode: TTreeNode; s: string): boolean;
var
QR:TADOQuery;
TmpNode:TTreeNode;
p:pchar;
begin
QR:=TADOQuery.Create(self);
if TNode=nil then //判断是否顶层接点 ;
begin
new(p);
p^.tcaption:=s;
p^.num:=1;
TNode:=Treeview1.Items.AddChildObject(TNode,p^.tcaption,p);
end;
with QR,treeview1 do
begin
close;
connection:=ADOCONNECTION1;
SQL.Clear;
SQL.Add('select parentid,id from 你的表 where condition');
//注意,condition中你可带参数,也可不带参数
parameters[0].Value:=s;//那么这句可要也可不要;
open;
ACTIVE;
first;
while not eof do
begin
new(p);
p^.tcaption:=QR.fieldbyname('parentid').AsString;
P^.num:=QR.fieldbyname('id').AsInteger;
TmpNode:=Items.AddChildObject(TNode,p^.tcaption,p);
ShowTree(TmpNode,p.tcaption);//递归
next;
end;
end;
end;
type
TForm1 = class(TForm)
TreeView1: TTreeView;
ADOConnection1: TADOConnection;
ADOQuery1: TADOQuery;
procedure FormCreate(Sender: TObject);
private
function FindParent(ID:String):TTreeNode;
procedure CreateTree;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
stlID:TStringList ;
implementation
{$R *.dfm}
function Tform1.FindParent(ID:String):TTreeNode;
var
i:Integer;
begin
result:=nil;
for i:=TreeView1.Items.Count-1 downto 0 do
if stlID.Strings[i]=ID then
begin
result:=TreeView1.Items[i];
break;
end;
end;
procedure Tform1.CreateTree;
var
tmpNode:TTreeNode;
begin
adoQuery1.SQL.Text:='select * from material order by ParentID';
adoQuery1.Open;
adoQuery1.First;
while not adoQuery1.Eof do
begin
tmpNode:=TreeView1.Items.AddChild(FindParent(adoQuery1.FieldByName('ParentID').AsString),adoQuery1.FieldByName('Name').AsString);
stlID.Add(adoQuery1.FieldByName('ID').AsString);//记录ID
adoQuery1.Next;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
createtree;
end;
WuLoveXue(晕死,又这样) :C++builder我不会,delphi也初学。
treeview的节点有一个data的指针属性,利用他可以把节点存储的信息读出来,
以下代码是递归删除选定节点下所有节点(包含子节点的节点,同时删除数据库数据):
注意:pchar在展开树节点时已申明。
procedure TForm1.detree(node: ttreenode);
var
tnode:ttreenode;
i:integer;
s1,s2:string;
begin
if node.HasChildren then
begin
for i:=node.Count-1 downto 0 do
begin
if node.Item[i].HasChildren then
detree(node.Item[i]);
s1:=pchar(node.Item[i].Data)^.mcaption;
s2:=pchar(node.Item[i].data)^.tcaption;
with form1.pub do
begin
close;
sql.Clear;
sql.Add('delete BOMMD where MD001=:AA and MD003=:BB');
parameters[0].Value:=s1;
parameters[1].Value:=s2;
ExecSQL;
end;
node.Item[i].Delete;
end;
end;
node.Delete;
end;
1、显示儿子会更好一点;
2、不需要重新生成树,只需要再增加一个节点就可以了;
3、给你一个简单的例子看看:
var
FirstNode,SecondNode: TTreeNode;
TreeView1.Items.Clear;
FirstNode := TreeView1.Items.AddFirst(TreeView1.Items.GetFirstNode, '系统角色');
AdoRole.Close;
AdoRole.SQL.Text := 'select * from RoleTable';
AdoRole.Open;
if AdoRole.RecordCount > 0 then
begin
AdoRole.First;
while not AdoRole.Eof do
begin
SecondNode := TreeView1.Items.AddChild(FirstNode, AdoRole.FieldByName('RoleName').AsString);
AdoUser.Close;
AdoUser.SQL.Text := 'select * from UserList where RoleID = '+AdoRole.FieldByName('RoleID').AsString+'';
AdoUser.Open;
while not AdoUser.Eof do
begin
TreeView1.Items.AddChild(SecondNode, AdoUser.FieldByName('Name').AsString);
AdoUser.Next;
end;
AdoRole.Next;
end;
end;
3、用递归:
首先,在单元接口部分声明一记录类型及其指针,用来保存你的树节点需传递的信息。
type
pchar=^str;
str=record
tcaption:string;
num:integer;
end;
写一生成树的函数,注意递归:
function TForm1.ShowTree(TNode: TTreeNode; s: string): boolean;
var
QR:TADOQuery;
TmpNode:TTreeNode;
p:pchar;
begin
QR:=TADOQuery.Create(self);
if TNode=nil then //判断是否顶层接点 ;
begin
new(p);
p^.tcaption:=s;
p^.num:=1;
TNode:=Treeview1.Items.AddChildObject(TNode,p^.tcaption,p);
end;
with QR,treeview1 do
begin
close;
connection:=ADOCONNECTION1;
SQL.Clear;
SQL.Add('select MD003,MD006 from BOMMD where MD001=:NN');
parameters[0].Value:=s;
open;
ACTIVE;
first;
while not eof do
begin
new(p);
p^.tcaption:=QR.fieldbyname('MD003').AsString;
P^.num:=QR.fieldbyname('MD006').AsInteger;
TmpNode:=Items.AddChildObject(TNode,p^.tcaption,p);
ShowTree(TmpNode,p.tcaption);//递归
next;
end;
end;
end;
然后在需要的时候调用该函数就可以了,例如:
procedure TForm1.FormCreate(Sender: TObject);
begin
ShowTree(nil,'0102-73316000');
end;
上述为一展BOM树的实例(BOM结构以关系数据库结构存储)。
2、不需重新生成树,直接调用
treeview1.items.addchildobject()即可增加子节点
1、右边显示儿子好。