100分treeview树形问题(在线等)

ou630j 2009-02-16 09:32:06
表 counode

nodecode varchar(30) 节点编号
nodename varchar(30) 节点名称
Parentcode varchar(30) 父节点编号

数据 nodecode nodename Parentcode
A10 广东 0
A20 广西 0
A30 广州 A10
A40 南宁 A20
A50 海珠 A30
A60 中山大学 A50


我现在想做一个树形的节点显示

显示效果如下
广东
广州
海珠
中山大学
广西
南宁
百色


可以多级节点增加,求具体代码
我只会一级一级,不会多级,急啊,最好同上面一样的,



...全文
222 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
wjk20021107 2009-02-19
  • 打赏
  • 举报
回复
兄弟,你应参考大家的方法,灵活运用吧。

我再次发一个给你看。有我先前发的递归方法,现新增点击节点新增子节点的方法。


-------------------------------------------------------------

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, DB, ADODB;

type
PDW = ^TDW;
TDW = record
DWBM :String; // 单位编码
DWMC :String; // 单位名称
FBM :String; // 单位父亲编码
end;
type
TForm1 = class(TForm)
TreeView1: TTreeView;
Button1: TButton;
ADOConnection1: TADOConnection;
ADOQuery1: TADOQuery;
TreeView2: TTreeView;
Button2: TButton;
Memo1: TMemo;
Memo2: TMemo;
procedure Button1Click(Sender: TObject);
procedure TreeView2Expanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
procedure CreateTrees(TreeV:TTreeView;SelNode:TtreeNode);
procedure CreateTrees2(TreeV:TTreeView;SelNode:TtreeNode);
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ ----------------------------------------------------------------------------
功能:创建树形单位
参数:TreeV:TTreeView 传入要生成单位树的 TTreeView 控件
SelNode: TtreeNode 当前单位节点
说明:采用递归方式创建
----------------------------------------------------------------------------}
procedure TForm1.CreateTrees(TreeV:TTreeView;SelNode: TtreeNode);
var SQLStr:String; i:integer ;
DNode:TtreeNode ;
ADOQ_Tree:TADOQuery ;
DWSSS:PDW ;
begin
try
ADOQ_Tree:=TADOQuery.Create(nil) ;
ADOQ_Tree.Connection := ADOConnection1 ;
// 判断传入的单位节点是否是空节点,是则生成根节点,不是则在传入的单位节点下生成新节点。
if SelNode = nil then begin
TreeV.Items.Clear ; // 清除树节点
SQLStr :='Select * From Tabc where Parentcode = ''0'' ';
ADOQ_Tree.Close ;
ADOQ_Tree.SQL.Clear ;
ADOQ_Tree.SQL.Text := SQLStr ;
ADOQ_Tree.Open ;
ADOQ_Tree.First ;
while not ADOQ_Tree.Eof do begin
New(DWSSS); // 创建单位节点信息指针
DWSSS.DWBM := ADOQ_Tree.fieldbyname('nodecode').AsString ;
DWSSS.DWMC := ADOQ_Tree.fieldbyname('nodename').AsString ;
DWSSS.FBM := ADOQ_Tree.fieldbyname('Parentcode').AsString ;

DNode :=TreeV.Items.AddChild(nil,DWSSS.DWMC); // 创建单位根节点
DNode.Data := DWSSS ; // 向节点赋隐含信息值

CreateTrees(TreeV,DNode); // 递归

ADOQ_Tree.Next ;
end;
end else begin
New(DWSSS); // 创建单位节点信息指针
DWSSS := SelNode.data ; // 将传入的单位节点数据信息赋值给一个指针变量

SQLStr :='Select * From Tabc where Parentcode = '''+DWSSS.DWBM+''' ';
ADOQ_Tree.Close ;
ADOQ_Tree.SQL.Clear ;
ADOQ_Tree.SQL.Text := SQLStr ;
ADOQ_Tree.Open ;
ADOQ_Tree.First ;
while not ADOQ_Tree.Eof do begin
New(DWSSS); // 创建单位节点信息指针
DWSSS.DWBM := ADOQ_Tree.fieldbyname('nodecode').AsString ;
DWSSS.DWMC := ADOQ_Tree.fieldbyname('nodename').AsString ;
DWSSS.FBM := ADOQ_Tree.fieldbyname('Parentcode').AsString ;

DNode :=TreeV.Items.AddChild(SelNode,DWSSS.DWMC); // 在传入的节点下生成子节点
DNode.Data := DWSSS ; // 向节点赋隐含信息值

CreateTrees(TreeV,DNode); // 递归

ADOQ_Tree.Next ;
end;
end;
finally
ADOQ_Tree.Free ;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
try
TreeView1.Items.BeginUpdate;

CreateTrees(TreeView1,nil);
Finally
TreeView1.Items.EndUpdate ;
end;
end;

{ ----------------------------------------------------------------------------
功能:创建树形单位
参数:TreeV:TTreeView 传入要生成单位树的 TTreeView 控件
SelNode: TtreeNode 当前单位节点
说明:采用点击节点创建
----------------------------------------------------------------------------}
procedure TForm1.CreateTrees2(TreeV:TTreeView;SelNode: TtreeNode);
const QSH= '请稍后...';
var SQLStr:String; i:integer ;
DNode:TtreeNode ;
ADOQ_Tree,ADOQ_T:TADOQuery ;
DWSSS:PDW ;
begin
try
ADOQ_Tree:=TADOQuery.Create(nil) ;
ADOQ_Tree.Connection := ADOConnection1 ;
ADOQ_T:=TADOQuery.Create(nil) ;
ADOQ_T.Connection := ADOConnection1 ;
// 判断传入的单位节点是否是空节点,是则生成根节点,不是则在传入的单位节点下生成新节点。
if SelNode = nil then begin
TreeV.Items.Clear ; // 清除树节点
SQLStr :='Select * From Tabc where Parentcode = ''0'' ';
ADOQ_Tree.Close ;
ADOQ_Tree.SQL.Clear ;
ADOQ_Tree.SQL.Text := SQLStr ;
ADOQ_Tree.Open ;
ADOQ_Tree.First ;
while not ADOQ_Tree.Eof do begin
New(DWSSS); // 创建单位节点信息指针
DWSSS.DWBM := ADOQ_Tree.fieldbyname('nodecode').AsString ;
DWSSS.DWMC := ADOQ_Tree.fieldbyname('nodename').AsString ;
DWSSS.FBM := ADOQ_Tree.fieldbyname('Parentcode').AsString ;

DNode :=TreeV.Items.AddChild(nil,DWSSS.DWMC); // 创建单位根节点
DNode.Data := DWSSS ; // 向节点赋隐含信息值

New(DWSSS);
DWSSS.DWBM := '' ;
DWSSS.DWMC := '' ;
DWSSS.FBM := '' ;
DNode :=TreeV.Items.AddChild(DNode,QSH); // 创建节点的“请稍后...”子节点
DNode.Data := DWSSS ;

ADOQ_Tree.Next ;
end;
end else begin
// 如果传入的节点没有子节点则退出操作
if SelNode.Count =0 then Exit ;
New(DWSSS);
// 取传入节点的第一个子节点,判断是否是“请稍后...”节点,是则删除
DWSSS := SelNode.getFirstChild.data ;
if trim(QSH) = trim(SelNode.getFirstChild.Text) then begin
SelNode.DeleteChildren ;
end;

New(DWSSS); // 创建单位节点信息指针
DWSSS := SelNode.data ; // 将传入的单位节点数据信息赋值给一个指针变量

SQLStr :='Select * From Tabc where Parentcode = '''+DWSSS.DWBM+''' ';
ADOQ_Tree.Close ;
ADOQ_Tree.SQL.Clear ;
ADOQ_Tree.SQL.Text := SQLStr ;
ADOQ_Tree.Open ;
ADOQ_Tree.First ;
while not ADOQ_Tree.Eof do begin
New(DWSSS); // 创建单位节点信息指针
DWSSS.DWBM := ADOQ_Tree.fieldbyname('nodecode').AsString ;
DWSSS.DWMC := ADOQ_Tree.fieldbyname('nodename').AsString ;
DWSSS.FBM := ADOQ_Tree.fieldbyname('Parentcode').AsString ;

DNode :=TreeV.Items.AddChild(SelNode,DWSSS.DWMC); // 在传入的节点下生成子节点
DNode.Data := DWSSS ; // 向节点赋隐含信息值

New(DWSSS);
DWSSS.DWBM := '' ;
DWSSS.DWMC := '' ;
DWSSS.FBM := '' ;
DNode :=TreeV.Items.AddChild(DNode,QSH); // 创建节点的“请稍后...”子节点
DNode.Data := DWSSS ;

ADOQ_Tree.Next ;
end;
end;
finally
ADOQ_Tree.Free ;
ADOQ_T.Free ;
end;
end;

procedure TForm1.TreeView2Expanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
begin
try
TreeView2.Items.BeginUpdate;

CreateTrees2(TreeView2,Node);
Finally
TreeView2.Items.EndUpdate ;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
try
TreeView2.Items.BeginUpdate;

CreateTrees2(TreeView2,nil);
Finally
TreeView2.Items.EndUpdate ;
end;
end;

end.




ou630j 2009-02-18
  • 打赏
  • 举报
回复
没有一个好用,还是自己后来找到一个
这什么地方来的,晕
sanguomi 2009-02-17
  • 打赏
  • 举报
回复
用递归效率太低了
数据多的话,慢得要死
zhxlsuyu1984 2009-02-17
  • 打赏
  • 举报
回复
我正在做的东西,其实就是一个递归算法嘛,你修改一下就可以了。如果看不懂联系我:QQ:6025056

procedure TMenuSetup.FormCreate(Sender: TObject);
begin
ShowTree;
end;

procedure TMenuSetup.ShowTree;
begin
tv1.Items.Clear;
tv1.Items.BeginUpdate;
//tv1.Images := il1;
root:=tv1.Items.AddFirst(nil,'根节点');
//root.ImageIndex := 0;
LoadTree(root,'0');
tv1.Items.EndUpdate;
tv1.FullExpand;
end;

procedure TMenuSetup.LoadTree(proot:TTreeNode;str:string);
var
MyNode:TTreeNode;
Query:TADOQuery;
strNodeName: string;
begin
Query:=TADOQuery.Create(Self);
Query.Connection:=DataModuleConn.con1;
Query.close;
Query.SQL.Clear;
Query.SQL.Add(' select * from t_sys_Menu where PMenuCode = ' + QuotedStr(str));
Query.Open;

while not Query.Eof do
begin

if (Query.FieldValues['IsUse'] = '1') then
begin
strNodeName := '[' + Query.FieldValues['MenuCode'] + ']' + Query.FieldValues['MenuName'];
end
else
begin
strNodeName := '[' + '停用' + ']' + '[' + Query.FieldValues['MenuCode'] + ']' + Query.FieldValues['MenuName'];
end;
MyNode := tv1.Items.AddChild(proot, strNodeName);

MyNode.Data := Pointer(Integer(Query.FieldValues['MenuCode']));
//MyNode.ImageIndex := 1;
Loadtree(MyNode, Query.FieldValues['MenuCode']);
Query.Next;
end;
end;
wjk20021107 2009-02-17
  • 打赏
  • 举报
回复
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, DB, ADODB;

type
PDW = ^TDW;
TDW = record
DWBM :String; // 单位编码
DWMC :String; // 单位名称
FBM :String; // 单位父亲编码
end;
type
TForm1 = class(TForm)
TreeView1: TTreeView;
Button1: TButton;
ADOConnection1: TADOConnection;
ADOQuery1: TADOQuery;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure CreateTrees(TreeV:TTreeView;SelNode:TtreeNode);
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ ----------------------------------------------------------------------------
功能:创建树形单位
参数:TreeV:TTreeView 传入要生成单位树的 TTreeView 控件
SelNode: TtreeNode 当前单位节点
----------------------------------------------------------------------------}
procedure TForm1.CreateTrees(TreeV:TTreeView;SelNode: TtreeNode);
var SQLStr:String; i:integer ;
DNode:TtreeNode ;
ADOQ_Tree:TADOQuery ;
DWSSS:PDW ;
begin
try
ADOQ_Tree:=TADOQuery.Create(nil) ;
ADOQ_Tree.Connection := ADOConnection1 ;
// 判断传入的单位节点是否是空节点,是则生成根节点,不是则在传入的单位节点下生成新节点。
if SelNode = nil then begin
TreeV.Items.Clear ; // 清除树节点
SQLStr :='Select * From Tabc where Parentcode = ''0'' ';
ADOQ_Tree.Close ;
ADOQ_Tree.SQL.Clear ;
ADOQ_Tree.SQL.Text := SQLStr ;
ADOQ_Tree.Open ;
ADOQ_Tree.First ;
while not ADOQ_Tree.Eof do begin
New(DWSSS); // 创建单位节点信息指针
DWSSS.DWBM := ADOQ_Tree.fieldbyname('nodecode').AsString ;
DWSSS.DWMC := ADOQ_Tree.fieldbyname('nodename').AsString ;
DWSSS.FBM := ADOQ_Tree.fieldbyname('Parentcode').AsString ;

DNode :=TreeV.Items.AddChild(nil,DWSSS.DWMC); // 创建单位根节点
DNode.Data := DWSSS ; // 向节点赋隐含信息值

CreateTrees(TreeV,DNode); // 递归

ADOQ_Tree.Next ;
end;
end else begin
New(DWSSS); // 创建单位节点信息指针
DWSSS := SelNode.data ; // 将传入的单位节点数据信息赋值给一个指针变量

SQLStr :='Select * From Tabc where Parentcode = '''+DWSSS.DWBM+''' ';
ADOQ_Tree.Close ;
ADOQ_Tree.SQL.Clear ;
ADOQ_Tree.SQL.Text := SQLStr ;
ADOQ_Tree.Open ;
ADOQ_Tree.First ;
while not ADOQ_Tree.Eof do begin
New(DWSSS); // 创建单位节点信息指针
DWSSS.DWBM := ADOQ_Tree.fieldbyname('nodecode').AsString ;
DWSSS.DWMC := ADOQ_Tree.fieldbyname('nodename').AsString ;
DWSSS.FBM := ADOQ_Tree.fieldbyname('Parentcode').AsString ;

DNode :=TreeV.Items.AddChild(SelNode,DWSSS.DWMC); // 在传入的节点下生成子节点
DNode.Data := DWSSS ; // 向节点赋隐含信息值

CreateTrees(TreeV,DNode); // 递归

ADOQ_Tree.Next ;
end;
end;
finally
ADOQ_Tree.Free ;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
CreateTrees(TreeView1,nil);
end;

end.
prabbit 2009-02-17
  • 打赏
  • 举报
回复
去下载一个DBTree控件,很好用、很方便。
bdmh 2009-02-16
  • 打赏
  • 举报
回复
Delphi(Pascal) code
PNodeInfo=^TNodeInfo //记录类型的指针变量
TNodeInfo=record //声明一个记录类型
ImageIndex:Integer;
//省略
end;

procedure BuildTree;
var
PNode:PNodeInfo;
begin
New(PNode); //分配空间
PNode.XXX:=XXX; //为记录中的字段赋值
ParentNode := FindTreeItem(Treeview,AddNodeInfo.ParentID); //找到node
Treeview.Items.AddObject(ParentNode, Trim(NodeText), Pointer(PNode));//用AddObject或AddChildObjec来添加结点或子结点
end;
Pointer(PNode),将指向记录的指针存到node的data中去,以后访问时可以PNodeInfo(node.data).xxx
ou630j 2009-02-16
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 liangpei2008 的回复:]
动态生成树是一种最基础的编程方法,还是别用控件了
另外最好在树的结点上挂一个结构体,便于扩展(一般情况下树结点可能包括ImageIndex,DllName,ID,Parent,NodeText,SelectedIndex等等)

Delphi(Pascal) code
PNodeInfo=^TNodeInfo
TNodeInfo=record
ImageIndex:Integer;
//省略
end;

procedure BuildTree;
var
PNode:PNodeInfo;
begin
New(PNode);
PNode.XXX:=XXX;
ParentNode := FindTreeItem(Treeview,AddNodeInfo.ParentID);
Treeview.Items.AddObject(ParentNode, Trim(NodeText), Pointer(PNode));//用AddObject或AddChildObjec来添加结点或子结点
end;



这个看不懂?能具体点吗?
liangpei2008 2009-02-16
  • 打赏
  • 举报
回复
动态生成树是一种最基础的编程方法,还是别用控件了
另外最好在树的结点上挂一个结构体,便于扩展(一般情况下树结点可能包括ImageIndex,DllName,ID,Parent,NodeText,SelectedIndex等等)

PNodeInfo=^TNodeInfo
TNodeInfo=record
ImageIndex:Integer;
//省略
end;

procedure BuildTree;
var
PNode:PNodeInfo;
begin
New(PNode);
PNode.XXX:=XXX;
ParentNode := FindTreeItem(Treeview,AddNodeInfo.ParentID);
Treeview.Items.AddObject(ParentNode, Trim(NodeText), Pointer(PNode));//用AddObject或AddChildObjec来添加结点或子结点
end;


ou630j 2009-02-16
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 bdmh 的回复:]
var
node:TTreeNode;


begin

node := TreeView1.Items.AddObject(nil,ADOQuery1.FieldByName('nodename').AsString,Pointer(ADOQuery1.FieldByName('nodecode').AsString));
node.HasChildren := True;//设置好这个属性,执行FullExpand,就会起作用了
end;
[/Quote]


执行有这种错误
Project Project1.exe raised exception class EOleException with message '字符串 '' 之前有未闭合的引号。'. Process stopped. Use Step or Run to continue.

procedure TForm1.Button1Click(Sender: TObject);
var node:TTreeNode;
begin
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'select * form counode where Parentcode=0';
ADOQuery1.Open;
while not ADOQuery1.Eof do
begin
node:=TreeView1.Items.AddObject(nil,ADOQuery1.FieldByName('nodename').AsString,PChar(ADOQuery1.FieldByName('nodecode').AsString));
node.HasChildren := True;//设置好这个属性,执行FullExpand,就会起作用了
ADOQuery1.Next;
end;
TreeView1.FullExpand;
end;

procedure TForm1.TreeView1Expanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
begin
Node.DeleteChildren;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'select * from counode where Parentcode'+QuotedStr(StrPas(Node.Data));
ADOQuery1.Open;
while not ADOQuery1.Eof do
begin
TreeView1.Items.AddChild(Node,ADOQuery1.FieldByName('nodename').AsString);
ADOQuery1.Next;
end;

end;


bdmh 2009-02-16
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 ou630j 的回复:]
引用 9 楼 bdmh 的回复:
第三方控件可以用dxdbtreelist或cxdbtreelist,设置id,和pid即可


这两个控件在那里下载啊
怎么我找不到
[/Quote]

控件可以到delphibox.com中找
bdmh 2009-02-16
  • 打赏
  • 举报
回复
var
node:TTreeNode;


begin

node := TreeView1.Items.AddObject(nil,ADOQuery1.FieldByName('nodename').AsString,Pointer(ADOQuery1.FieldByName('nodecode').AsString));
node.HasChildren := True;//设置好这个属性,执行FullExpand,就会起作用了
end;
ou630j 2009-02-16
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 bdmh 的回复:]
第三方控件可以用dxdbtreelist或cxdbtreelist,设置id,和pid即可
[/Quote]

这两个控件在那里下载啊
怎么我找不到
ou630j 2009-02-16
  • 打赏
  • 举报
回复
无语,知不知道expanding如何用呀,
TreeView1.FullExpand;//全部展开
TreeView1.Selected.Expand(True);//所选节点展开
执行展开操作时,就会触发,你添加最上及之后,执行TreeView1.FullExpand;

另外,在TreeView1.Items.AddObject(nil,ADOQuery1.FieldByName('nodename').As…
[/Quote]




加上了TreeView1.FullExpand;//全部展开 这个都还是没有反应的
还是
广东
广西

另外,在TreeView1.Items.AddObject(nil,ADOQuery1.FieldByName('nodename').AsString,Pointer(ADOQuery1.FieldByName('nodecode').AsString)); 后,把添加的item的HasChildren属性设置为true
这怎么做的
TreeView1.Items.
simonhehe 2009-02-16
  • 打赏
  • 举报
回复
是要这句吗?

TreeView1.FullExpand;
bdmh 2009-02-16
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 ou630j 的回复:]
引用 8 楼 bdmh 的回复:
Expanding,当节点打开时执行



都说了,他不会执行,要不然,我还问来干嘛?
[/Quote]

无语,知不知道expanding如何用呀,
TreeView1.FullExpand;//全部展开
TreeView1.Selected.Expand(True);//所选节点展开
执行展开操作时,就会触发,你添加最上及之后,执行TreeView1.FullExpand;

另外,在TreeView1.Items.AddObject(nil,ADOQuery1.FieldByName('nodename').AsString,Pointer(ADOQuery1.FieldByName('nodecode').AsString)); 后,把添加的item的HasChildren属性设置为true
ou630j 2009-02-16
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 bdmh 的回复:]
[/Quote]


用了那个打开得到的树形节点效果是

广东
广西

其它就没有了,需要设置那里的
ou630j 2009-02-16
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 scutLiu 的回复:]
读数据库时需要多次循环遍历
首先根据父结点是为空nil找打所有一级节点
然后再对一节节点逐个遍历找到其子节点(以此类推)

至于将数据加载的treeview控件中
则可以使用1楼的方法
[/Quote]

scutLiu 这个我也会说,可做出来的效果不对,所以才问?
ou630j 2009-02-16
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 bdmh 的回复:]
Expanding,当节点打开时执行
[/Quote]


都说了,他不会执行,要不然,我还问来干嘛?



scutLiu 2009-02-16
  • 打赏
  • 举报
回复
读数据库时需要多次循环遍历
首先根据父结点是为空nil找打所有一级节点
然后再对一节节点逐个遍历找到其子节点(以此类推)

至于将数据加载的treeview控件中
则可以使用1楼的方法
加载更多回复(9)

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧