如何动态创建treeView的树型目录?(50分)

  • 主题发起人 主题发起人 strchi
  • 开始时间 开始时间
S

strchi

Unregistered / Unconfirmed
GUEST, unregistred user!
我从表中根据level属性来创建treeview的目录,可是不知道树型目录是怎么动态创建的,书上的那个例子讲的是删除,不知道那位大侠能指点一二,
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
d:TTreeNode;
begin
with table1 do
begin
close;
Filtered:=false;
filter:=’LEVEL=’+#39+’1’+#39;
Filtered:=true;
open;
end;
Table1.First;
while not Table1.Eof do
begin
// Treeview1.Items.Create(d);
Table1.Next;
end;
end;
 
只根据层号是不够的,
必须知道每个节点的父节点,
如果没有父节点,则作为根节点,
创建时可以仅创建第一层节点,
当需要展开时,再读取并添加其子节点,
这样的话,不需要递归,初始化很快,
像Delphi的SQL Explorer
 
treeview1.items.add;
 
说得太简单,我看不懂,
我先
var d:TTreeView;
begin
treeview1.items.add(dd,'谢谢你,请帮忙看看!');
end;
是可以的,为什么我连着写就不行,提示好像是没有初始化
那个大哥给一段代码给我看看吧。
 
treeview1.Items.AddChild(nil,'你的内容'); // 第一级
treeview1.Items.AddChild(treeview1.Items[0],'你的内容'');//下一级
 
没人给你回答
可能是太简单了,学习Delphi应该自己多动动脑子
否则,怎么才能有提高
我给你一个解析xml的东西吧,好好理解,也是树形结构

//用了D6里的xml控件
//函数体
procedure TForm1.ReadXMLTree(RootTreeNode:TTreeNode; XMLTreeNode:IXMLNode);
var i:integer; c:TTreeNode;
begin
for i:=0 to XMLTreeNode.ChildNodes.Count-1 do
begin
c:=xmltree.Items.AddChild(RootTreeNode,XMLTreeNode.ChildNodes.Nodes.NodeName);
ReadXMLTree(c,XMLTreeNode.ChildNodes.Nodes);
end;
end;
//调用
procedure TForm1.Button2Click(Sender: TObject);
begin
ReadXMLTree(nil,XMLDocument1.Node);
end;
 
一、指标树的建立

具体方法是:创建一个数据库,设计指标表t_pub_index,包含index_id、parent_id、index_name字段,其它字段根据实际业务而定,指标名称index_name将在树型控件的节点上显示,index_id字段保存节点的唯一标识号,parent_id表示当前节点的父节点号,标识号组成了一个“链表”,记录了树上节点的结构。设计一窗体Frm_sys_index,其上放置TreeView控件tv_zb、Query控件Query1及其它指标属性编辑显示控件。一个树的节点又包含文本(Text)和数据(Data)。Text为String类,用来显示指标或指标目录名称。Data则为无定形指针(Untyped Pointer),可以指向一个与节点相联系的数据结构,该结构与数据库指标表相应域关联,如指标ID、上级节点ID。

Query控件的表达式为:

select index_id, parent_id, index_name from t_pub_index

start with index_id=0 connect by prior index_id=parent_id

其中start with 和connect by 是Oracle的SQL语句的保留字,使一条记录的parent_id列的值等于前一记录的index_id列的值,并以parent_id等于0的记录开始。

建树的基本思路是:

procedure TFrm_sys_index.createtree;

var

curValue: indexPointer; //指向与节点相联系的数据结构的指针

curNode : TTreeNode; //当前节点

curid : integer; //当前节点标识号

begin

curNode := nil;

curid := -1;

Query_index.Open;

Query_index.first;

while not Query_index.Eof do

begin

new(curValue);

With curValue^ do

将数据库指标表t_pub_index各字段值赋curValue 所指数据结构

while(curid <> curValue.parent_id) do //当前节点的标识号不等于当前记录的父节点号

begin

curNode := curNode.parent;

curid:= indexPointer(curNode.data).index_id;

end;

curNode := tv_zb.Items.AddChildObject(curNode,

curValue^.index_name,curValue); //在当前节点上添加子节点,显示节点指标名称,所带指针指向一个与指标数据相联系的数据结构

curid := indexPointer(curNode.data).index_id;

Query_index.next;

end;

Query_index.close;

end;

二、增加、删除、修改树节点

单纯在Treeview 上增加、删除、修改节点只需用它本身提供的Treeview.Items. AddChildObject、 Treeview.Selected.Delete、Treeview.Selected.EditText等方法即可,但要相应修改数据库中的数据,必须通过递归调用同一个函数(用于删除一个选项)来遍历所选节点下的所有子节点。下面以删除节点为例介绍具体实现流程:

function TFrm_sys_index.delnode(node1:TTreenode):TTreenode;

var

childnode:TTreenode;

begin

childnode:=node1.GetLastChild; //按倒序获得子项,因为删除选项时,列表会发生变化

while childnode<>nil do

childnode:=delnode(childnode); //如子项不为空,进行递归调用

index_id:=inttostr(indexpointer(node1.data).index_id);//获得该节点对应指标

在数据库删除相应指标;

result:=node1.parent.GetPrevChild(node1); //定位到该节点的上一节点

node1.delete; //删除树节点

end;

三、拖动树节点

拖动树节点基本上是通过建立目标项的新子项、向它复制源项、删除原项来移动选项。与上述删除操作相似,也是通过递归调用同一个函数(用于移动一个选项),按倒序移动所选节点下的所有子节点。下面是递归过程的代码:

procedure TFrm_sys_index.CopyNodeUnder(treeview:TTreeview;

sourcenode,targetnode:ttreenode);

var

newnode:ttreenode;

i:integer;

begin

newnode:=treeview.items.addchildfirst(targetnode,''); //建立目标项

newnode.assign(sourcenode); //复制源项属性

for i:=sourcenode.count-1 downto 0 do //递归调用,按倒序移动其所有子项

CopyNodeUnder (treeview,sourcenode.item,newnode);

treeview.items.delete(sourcenode); //删除源项

end;

Treeview对拖动操作提供支持,我们将组件的DragKind属性设置为dkDrag,DragMode属性设置为dmAutomatic,并为OnDragOver与OnDragDrop事件编写了处理程序。OnDragOver事件处理程序对允许移动的条件进行判断,排除需要避免的特殊情况。代码如下:

procedure TFrm_sys_index.tv_zbDragOver(Sender, Source: TObject; X,

Y: Integer; State: TDragState; var Accept: Boolean);

var

targetnode,sourcenode:TTreenode;

begin

targetnode:=tv_zb.getnodeat(x,y);

if (Source=Sender) and (targetnode<>nil) then //保证移动在TreeView上,且目标节点不为空

begin

Accept:=true;

sourcenode:=tv_zb.selected;

//以下代码防止用户将一个选项拖到其子项上(它会随着选项一起移动,导致死循环)

while (targetnode.parent<>nil) and (targetnode <> sourcenode) do

targetnode:=targetnode.parent;

if (targetnode = sourcenode) then Accept:=false;

end

else Accept:=false;

end;

OnDragDrop事件处理程序启动前述移动过程CopyNodeUnder,修改数据库数据。此外,在大批量添加数据到Treeview中时最好使用TreeView.Items.BeginUpdate和  TreeView.Items.EndUpdate,这样能加快显示速度。大致流程如下:

procedure TFrm_sys_index.tv_zbDragDrop(Sender, Source: TObject; X,

Y: Integer);

var

targetnode,sourcenode:TTreenode;

begin

targetnode:=tv_zb.getnodeat(x,y); //获得源节点

sourcenode:=tv_zb.selected; //获得目标节点

修改数据库中当前节点的父节点号parent_id,使其等目标节点标识号;

tv_zb.items.beginupdate; //禁用TreeView重绘操作

try

copynodeunder(tv_zb,sourcenode,targetnode); //启动移动过程

tv_zb.selected:=targetnode;

finally

tv_zb.items.endupdate; //重新设置

end;

end;
 
多人接受答案了。
 
后退
顶部