关于Ttreeview的简单使用!(200分)

  • 主题发起人 主题发起人 oulin
  • 开始时间 开始时间
O

oulin

Unregistered / Unconfirmed
GUEST, unregistred user!
要求:
1、对根节点的添加和删除。(添加的内容来自数据库)
2、对子节点的添加和删除(4级节点)。
3、怎样使子节点接受单击事件。
4、请给出代码来。

(我看过以前的记录,不过太复杂了,看不懂,:),所以要简单明了为好!)[?]

 
FlowNode := DataTreeView.Items.AddChild(ProgramNode, 'aaaa');
FlowNode.ImageIndex := 2;
FlowNode.SelectedIndex := 3;

AddChild(上级节点, 节点标题)

如上级节点为空,哪就是第一级节点。

FlowNode.Delete; //不论哪个节点都可这样删了

节点无法接受单击事件,

你可以用
if TDataTreeView(Sender).Selected.Level = 0 then
来判断是哪一级结点,为0就是第一级

也可用
if TDataTreeView(Sender).Selected.text = '标题' then
来判断是哪一个结点,

这些写在TDataTreeView的OnClick事件中。

如要例程,我可寄给你一个
 
devexpress dbtree
is very good
its demo can help you
 
go7.163.com/luyear/delphi.htm
 
  我们都知道,开发者主要用Delphi来开发数据库管理软件,正因如此,树型控件的使用
最好与数据库联系起来。Delphi提供了一个树型控件TTreeView,可以用来描述复杂的层次
关系。

  1.树节点信息的存储和加载

  常用的方法是用树控件的 LoadFromFile和SavetoFile方法,来实现树控件和文件之间
的交互;或用Assign方法实现树控件和DBMemo,也就是和数据库间的交互。该方法的优点是
编程相对简单,缺点是树控件的实际节点数可能会很大,对于“大树”,每次加载和存储的
数据量会加大,将降低速度,增大系统开销,造成数据冗余。另一种方法,就是只在树上产
生“看得见”的节点,没有专门记录全部树节点结构的文件或数据库字段,而将树节点结构
分散在数据库的每一个记录中。

  具体方法是:创建一个数据库,字段根据实际业务而定,其中必然有一个字段的信息将
在树型控件的节点上显示,另外还要一个字段来保存节点的惟一标识号,该标识号由长度相
等的两部分组成,前段表示当前节点的父节点号,后段表示当前节点的节点号,此标识号相
当于一个“链表”,记录了树上节点的结构。该方法的优点:用户操作“大树”时,一般不
会展开所有的节点,而只用到有限的一部分,同时只能从树根一层一层地展开,该法只在树
上产生“看得见”的节点,所以,存储和加载“大树”的速度快,数据量小,系统开销和数
据冗余较小。缺点:编程较复杂,但可以结合该方法编成一个新的树控件,将大大提高编程
效率。值得注意的是,ID号必须惟一,所以在编程中如何合理产生ID尤为重要。

  2.数据库结构示例

  创建一个数据库,为简化程序,我只创建两个数据库字段,定义如下:

  字段名 类型 长度

  Text C 10

  LongID C 6

  LongID字段实际上由两段组成,每一段3位,LongID只能表示1000条记录。将LongID定
义为索引字段,存为c:/testtree/tree.dbf。编辑该DBF文件,新建一条记录,Text字段设
为TOP,LongID字段设为“000”(3个“0”前为三个空格)。

  3.创建演示程序

  在Form1上放置TreeView1、Table1、PopupMenu1、Edit1、Edit2。TreeView1的PopupMenu
属性设为PopupMenu1;Table1的DataBaseName属性设为c:/testtree,TableName属性设为tree.dbf,
IndexFieldNames属性设为LongID;为PopupMenu1加选单项Add1和Del1,Caption分别为Add
和Del;Edit1用来输入新节点的Text属性值,Edit2用来输入新节点的3位ID号。存为
c:/testtree/treeunit.pas和c:/testtree/testtree.dpr。

  在treeunit.pas的Type关键字后加入一行:Pstr:^string;{Pstr为字符串指针}

  为Form1的OnCreate事件添加代码:
  procedure TForm1.FormCreate(Sender: TObject);
  var p:Pstr;Node:TTreeNode;
  begin
  with Table1,Treeview1 do
  begin
  open;
  first;
  new(p);{为指针p分配内存}
  p^:=FieldByName(′LongID′).AsString;
  Node:=Items.AddChildObject(nil,FieldByName(′Text′).AsString,p);
  if HasSubInDbf(Node) then Items.AddChildObject(Node,′ ′,nil);{有子节点则加
一个空子节点}
  end;
  end;

  HasSubInDbf为自定义函数,自变量为Node,检查节点Node有无子节点,有则返回True,
反之返回False,并在TForm1的类定义里加入原型声明(其它自定义函数的原型也在TForm1的
类定义里声明,不另作解释),函数代码如下:

  function TForm1.HasSubInDbf(Node:TTreeNode):Boolean;
  begin
  with Table1 do
  begin
  Table1.FindNearest([copy(Pstr(Node.Data)^,4,3)+′000′]);
  result:=copy(FieldByName(′LongID′).AsString,1,3)=copy(Pstr(Node.Data)^,4,3);
{如数据库里当前记录的LongID字段内容的前3位和节点Node的Data的后3位相同,则Node应该有子节点}
  end;
  end;

  为TreeView1控件的OnDeletion事件添加代码,需要指出的是,不仅调用Delete方法可以
触发OnDeletion事件,而且当树控件本身被释放前,也触发OnDeletion事件,所以,在此处
加入dispose(node.data)会很“安全”:

  procedure TForm1.TreeView1Deletion(Sender: TObject; Node: TTreeNode);

  begin
  Dispose(Node.Data);{释放节点数据内存}
  end;
  为Add1选单项的OnClick事件添加代码如下:
  procedure TForm1.Add1Click(Sender: TObject);
  var p:pstr;Tmpstr:string;i:integer;
  begin
  try
  StrToInt(Edit2.Text);
  Tmpstr:=Edit2.Text;{注:在实用中,必须用更好的方法来产生ID}
  except;
  ShowMessage(′重新输入Edit2的内容′);
  abort;
  end;
  with TreeView1 do
  begin
  new(p);
  p^:=copy(Pstr(Selected.Data)^,4,3)+TmpStr;
  Items.AddChildObject(Selected,Edit1.Text,p);
  end;
  with Table1 do{ 在数据库里添加记录 }
  begin
  Append;
  FieldByName(′Text′).AsString:=Edit1.text;
  FieldByName(′LongID′).AsString:=p^;
  Post;
  end;
  TmpStr:=inttostr(strtoint(TmpStr)+1);
  for i:=length(TmpStr) to 2 do TmpStr:=′0′+TmpStr;
  Edit2.Text:=TmpStr;
  end;
  为Del1菜单项的OnClick事件添加代码如下:
  procedure TForm1.Del1Click(Sender: TObject);
  var DelList:TStringList;LongID,NSubLongID:string;
  begin
  DelList:=TStringList.create;
  DelList.Sorted:=True;
  DelList.Add(Pstr(TreeView1.Selected.Data)^);
  while DelList.Count>0 do
  begin
  LongID:=DelList.Strings[0];
  DelList.Delete(0);
  Table1.SetKey;
  Table1.FieldByName(′LongID′).AsString:=LongID;
  if Table1.GotoKey then Table1.Delete;
  if HasSubInDbf(TreeView1.Selected) then
  begin
  NSubLongID:=Table1.FieldByName(′LongID′).AsString;
  while (copy(NSubLongID,1,3)=copy(LongID,4,3))and(not Table1.Eof) do
  begin
  dellist.Add(NSubLongId);
  Table1.Next;
  NSubLongId:=Table1.FieldByName(′LongID′).AsString;
  end;
  end;
  end;
  DelList.Free;
  TreeView1.Items.Delete(TreeView1.Selected);
  end;
  为TreeView1的OnExpanding事件添加代码:
  procedure TForm1.TreeView1Expanding(Sender: TObject; Node: TTreeNode;
  var AllowExpansion: Boolean);
  var TmpNode:TTreeNode;NSubLongID:String;p:Pstr;bm:TBookMark;
  begin
  with Table1,TreeView1 do
  begin
  Items.BeginUpdate;
  SetKey;
  FieldByName(′LongID′).AsString:=Pstr(Node.Data)^;
  if not GotoKey then Items.Delete(Node)
  else
  begin
  TmpNode:=Node.GetFirstChild;
  if (TmpNode.Text=′ ′)and(TmpNode.Data=nil) then
  begin
  TmpNode.Delete;
  if HasSubInDbf(Node) then
  begin
  NSubLongID:=FieldByName(′LongID′).AsString;
  while (copy(NSubLongID,1,3)=copy(Pstr(Node.Data)^,4,3))and(not Eof) do
  begin
  new(p);
  p^:=FieldByName(′LongID′).AsString;
  bm:=GetBookMark;
  TmpNode:=Items.AddChildObject(Node,FieldByName(′Text′).AsString,p);
  if HasSubInDbf(TmpNode) then Items.AddChildObject(TmpNode,′ ′,nil);
  GotoBookMark(bm);
  FreeBookMark(bm);
  Next;
  NSubLongId:=FieldByName(′LongID′).AsString;
  end; end; end;
  end;
  Items.EndUpdate;
  end;
  end;

  以上简要谈了谈数据库的树状显示的基本方法,另外,编辑树上节点的Text属性的同时
对数据库进行修改、同一数据库在多用户同时操作时数据库以及树的一致性、树上节点的拷
贝与复制等就不再赘述,读者可自行完善。

 
程云兄,
给你的examples来学习学习吧!
我的e-mail:oulin001@sohu.com
 
我也需要例子。
haipeng@cmmail.com
 
”诚实男人“
你的东东好象很面熟,:),可我看不懂啊!
都怪我太水了!
 
我上传到了http://delphi.mychangshu.com/
这是栋栋的Delphi开发者资源社区,

连接地址为 http://delphi.mychangshu.com/dispdoc.asp?id=338

可自行下载,写的简单,勿笑呀!
 
可以把你的问题说的详细一点吗?
如果方便,请把你的数据表结构发送一下!
 
这个想必能看懂!
如果还有更好的,望高手能贴出来!

Edit1.Text:=TreeView.Selected.Text; //当前节点内容

Edit2.Text:=TreeView.Selected.Parent.Text //父节点内容

Edit3.Text:=inttostr(TreeView.Selected.Count); //下级节点数

Edit4.Text:=inttostr(TreeView.Selected.Index); //同级别的索引号

Edit5.Text:=inttostr(TreeView.Selected.Level); //当前级别

Edit8.Text:=inttostr(TreeView.Items.Count); //总节点数

Edit6.Text:=inttostr(TreeView.Selected.AbsoluteIndex); //全文索引号

Edit7.text:=TreeView.FindNextToSelect.Text; //下一节点内容

TreeView.FullExpand; //展开全部节点

TreeView.FullCollapse;//收缩全部节点

TreeView.Selected.Delete//删除当前节点及子节点

TreeView.Items.AddChild(TreeView.Selected,Text); //添加子节点,Text为内容可用变量赋值

TreeView.Selected.Expand(TreeView.Selected.Expanded);//展开当前节点

TreeView.Items.Add(TreeView.Selected,Text);//添加本级节点,Text为内容可用变量赋值

 
接受事件就更容易了!
比如说单击事件!
begin
if TreeView.selected.text='OK' then //如果所节点的节点内容为’XX‘
这里就是你想要做的了
end;
不知道还有没有更好的方法!
 
aa
cc
dd
yy
zz
ee
bb
具体点吧,能用程序在treeview里写这样的结果出来就行了!
然后当我单击"yy"或"zz”时响应我的事件!
最好能写清楚点!解析清楚点!:)
谢谢各为!
好了就送分!!
 
后退
顶部