linux社区爱心援助Linux认证系列教程业界动态站务新闻公司招聘网络学院网址大全LPI专题CISCO专题
设为首页
加入收藏
管理团队
JSP  
JAVA  
PERL  
 您的位置:首页 > 开发语言 > Delphi >
栏目导栏
  php
  JSP
  ASP
  asp.net
  JAVA
  c/c++/c#
  perl
  JavaScript
  Basic
  Delphi
资料搜索
热门文章
·HexToStr函数和StrToHex函数
·Delphi中的进制转换
·delphi轻松设置无边框透明窗体
·delphi第三方控件安装(Ehlib)
·DELPHI组件安装全攻略
·delphi动态创建控件
·开发工具比较Visual C++ VS De
·delphi完整身份证效验程序实例
·delphi中的Format函数详解
·delphi编程获取打印机的打印任
·如何判断文本文件的编码格式
·深入研究Variant数组
·用delphi编写网络游戏的外挂
·Delphi技巧-用户自定义数据类型
·delphi设置控件透明
最新文章
·在应用程序中跟踪MOUSE的坐标
·压缩和修复MS Access 2000文件
·DELPHI 6.0 动画制做
·怎样在Delphi中调用LastError信
·怎样得到主域服务器名称
·怎样利用递归实现删除某一目录
·读出主键下所有项
·如何制作照片底片效果的图像(
·获得Modem的状态
·WebBrowser屏幕滚动的实现,设
·有关字符串处理的小技巧
·Delphi建立键盘鼠标动作纪录与
·Delphi中布尔类型辨析
·DELPHI程序注册码设计
·图形的不规则的Copy
Google
 
Delphi中树型控件的使用技巧
[ 作者:  加入时间:2007-10-30 15:41:50  来自:Linux联盟收集整理 ]
我们都知道,开发者主要用Delphi来开发数据库管理软件,正因如此,树型控件的使用最好与数据库联系起来。Delphi提供了一个树型控件TTreeView,可以用来描述复杂的层次关系。CUxLinux联盟
CUxLinux联盟
  树节点信息的存储和加载CUxLinux联盟
CUxLinux联盟
  常用的方法是用树控件的 LoadFromFile和SavetoFile方法,来实现树控件和文件之间的交互;或用Assign方法实现树控件和DBMemo,也就是和数据库间的交互。该方法的优点是编程相对简单,缺点是树控件的实际节点数可能会很,对于“大树”,每次加载和存储的数据量会加大,将降低速度,增大系统开销,造成数据冗余。另一种方法,就是只在树上产生“看得见”的节点,没有专门记录全部树节点结构的文件或数据库字段,而将树节点结构分散在数据库的每一个记录中。CUxLinux联盟
CUxLinux联盟
  具体方法是:创建一个数据库,字段根据实际业务而定,其中然有一个字段的信息将在树型控件的节点上显示,另外还要一个字段来保存节点的惟一标识号,该标识号由长度相等的两部分组成,前段表示当前节点的父节点号,后段表示当前节点的节点号,此标识号相当于一个“链表”,记录了树上节点的结构。该方法的优点:用户操作“大树”时,一般不会展开所有的节点,而只用到有限的一部分,同时只能从树根一层一层地展开,该法只在树上产生“看得见”的节点,所以,存储和加载“大树”的速度快,数据量小,系统开销和数据冗余较小。缺点:编程较复杂,但可以结合该方法编成一个新的树控件,将大大提高编程效率。值得注意的是,ID号必须惟一,所以在编程中如何合理产生ID尤为重要。CUxLinux联盟
CUxLinux联盟
  数据库结构示例CUxLinux联盟
CUxLinux联盟
  创建一个数据库,为简化程序,我只创建两个数据库字段,定义如下:CUxLinux联盟
字段名 类型 长度CUxLinux联盟
text c 10CUxLinux联盟
longid c 6 CUxLinux联盟
CUxLinux联盟
  LongID字段实际上由两段组成,每一段3位,LongID只能表示1000条记录。将LongID定义为索引字段,存为c: esttree ree.dbf。编辑该DBF文件,新建一条记录,Text字段设为TOP,LongID字段设为“000”(3个“0”前为三个空格)。CUxLinux联盟
CUxLinux联盟
  创建演示程序CUxLinux联盟
CUxLinux联盟
  在Form1上放置TreeView1、Table1、PopupMenu1、Edit1、Edit2。TreeView1的PopupMenu属性设为PopupMenu1;Table1的DataBaseName属性设为c: esttree,TableName属性设为tree.dbf,IndexFieldNames属性设为LongID;为PopupMenu1加选单项 Add1和Del1,Caption分别为Add和Del;Edit1用来输入新节点的Text属性值,Edit2用来输入新节点的3位ID号。存为c: esttree reeunit.pas和c: esttree esttree.dpr。CUxLinux联盟
  在treeunit.pas的Type关键字后加入一行:Pstr=^string;{Pstr为字符串指针}CUxLinux联盟
  为Form1的OnCreate事件添加代码:CUxLinux联盟
CUxLinux联盟
  procedure TForm1.FormCreate(Sender: TObject);CUxLinux联盟
  var p:Pstr;Node:TTreeNode;CUxLinux联盟
  beginCUxLinux联盟
     with Table1,Treeview1 doCUxLinux联盟
       beginCUxLinux联盟
         open;CUxLinux联盟
         first;CUxLinux联盟
         new(p);{为指针p分配内存}CUxLinux联盟
         p^:=FieldByName('LongID').AsString;CUxLinux联盟
         Node:=Items.AddChildObject(nil,FieldByName('Text').AsString,p);CUxLinux联盟
         if HasSubInDbf(Node) then Items.AddChildObject(Node,' ',nil);{有子节点则加一个空子节点}CUxLinux联盟
         end;CUxLinux联盟
     end;
CUxLinux联盟
CUxLinux联盟
  HasSubInDbf为自定义函数,自变量为Node,检查节点Node有无子节点,有则返回True,反之返回False,并在TForm1的类定义里加入原型声明(其它自定义函数的原型也在TForm1的类定义里声明,不另作解释),函数代码如下:CUxLinux联盟
CUxLinux联盟
CUxLinux联盟
  function TForm1.HasSubInDbf(Node:TTreeNode):Boolean;CUxLinux联盟
  beginCUxLinux联盟
     with Table1 doCUxLinux联盟
      beginCUxLinux联盟
         Table1.FindNearest([copy(Pstr(Node.Data)^,4,3)+'000']);CUxLinux联盟
         result:=copy(FieldByName('LongID').AsString,1,3)=copy(Pstr(Node.Data)^,4,3); {如数据库里当前记录的LongID字段内容的前3位和节点Node的Data的后3位相同,则Node应该有子节点}CUxLinux联盟
         end;CUxLinux联盟
      end;CUxLinux联盟
CUxLinux联盟
  为TreeView1控件的OnDeletion事件添加代码,需要指出的是,不仅调用Delete方法可以触发OnDeletion事件,而且当树控件本身被释放前,也触发OnDeletion事件,所以,在此处加入dispose(node.data)会很“安全”:CUxLinux联盟
  CUxLinux联盟
procedure TForm1.TreeView1Deletion(Sender: TObject; Node: TTreeNode);CUxLinux联盟
  beginCUxLinux联盟
     Dispose(Node.Data);{释放节点数据内存}CUxLinux联盟
    end;
CUxLinux联盟
  为Add1选单项的OnClick事件添加代码如下:CUxLinux联盟
CUxLinux联盟
  procedure TForm1.Add1Click(Sender: TObject);CUxLinux联盟
  var p:pstr;Tmpstr:string;i:integer;CUxLinux联盟
  beginCUxLinux联盟
     tryCUxLinux联盟
       StrToInt(Edit2.Text);CUxLinux联盟
      Tmpstr:=Edit2.Text;{注:在实用中,必须用更好的方法来产生ID}CUxLinux联盟
       except;CUxLinux联盟
      CUxLinux联盟
       ShowMessage('重新输入Edit2的内容');CUxLinux联盟
        abort;CUxLinux联盟
         end;CUxLinux联盟
       with TreeView1 doCUxLinux联盟
         beginCUxLinux联盟
           new(p);CUxLinux联盟
           p^:=copy(Pstr(Selected.Data)^,4,3)+TmpStr;CUxLinux联盟
           Items.AddChildObject(Selected,Edit1.Text,p);CUxLinux联盟
           end;CUxLinux联盟
      CUxLinux联盟
         with Table1 do{ 在数据库里添加记录 }CUxLinux联盟
           beginCUxLinux联盟
             Append;CUxLinux联盟
             FieldByName('Text').AsString:=Edit1.text;CUxLinux联盟
             FieldByName('LongID').AsString:=p^;CUxLinux联盟
             Post;CUxLinux联盟
             end;CUxLinux联盟
        CUxLinux联盟
           TmpStr:=inttostr(strtoint(TmpStr)+1);CUxLinux联盟
           for i:=length(TmpStr) to 2 do TmpStr:='0'+TmpStr;CUxLinux联盟
           Edit2.Text:=TmpStr;CUxLinux联盟
          end;
CUxLinux联盟
CUxLinux联盟
  为Del1菜单项的OnClick事件添加代码如下:CUxLinux联盟
  procedure TForm1.Del1Click(Sender: TObject);CUxLinux联盟
  var DelList:TStringList;LongID,NSubLongID:string;CUxLinux联盟
  beginCUxLinux联盟
   DelList:=TStringList.create;CUxLinux联盟
   DelList.Sorted:=True;CUxLinux联盟
   DelList.Add(Pstr(TreeView1.Selected.Data)^);CUxLinux联盟
   while DelList.Count>0 doCUxLinux联盟
   beginCUxLinux联盟
   LongID:=DelList.Strings[0];CUxLinux联盟
   DelList.Delete(0);CUxLinux联盟
   Table1.SetKey;CUxLinux联盟
   Table1.FieldByName('LongID').AsString:=LongID;CUxLinux联盟
   if Table1.GotoKey then Table1.Delete;CUxLinux联盟
   if HasSubInDbf(TreeView1.Selected) thenCUxLinux联盟
   beginCUxLinux联盟
   NSubLongID:=Table1.FieldByName('LongID').AsString;CUxLinux联盟
   while (copy(NSubLongID,1,3)=copy(LongID,4,3))and(not Table1.Eof) doCUxLinux联盟
   beginCUxLinux联盟
   dellist.Add(NSubLongId);CUxLinux联盟
   Table1.Next;CUxLinux联盟
   NSubLongId:=Table1.FieldByName('LongID').AsString;CUxLinux联盟
   end;CUxLinux联盟
  end;CUxLinux联盟
CUxLinux联盟
   end;CUxLinux联盟
   DelList.Free;CUxLinux联盟
   TreeView1.Items.Delete(TreeView1.Selected);CUxLinux联盟
  end;
CUxLinux联盟
CUxLinux联盟
   为TreeView1的OnExpanding事件添加代码:CUxLinux联盟
CUxLinux联盟
  procedure TForm1.TreeView1Expanding(Sender: TObject; Node: TTreeNode;CUxLinux联盟
   var AllowExpansion: Boolean);CUxLinux联盟
  var TmpNode:TTreeNode;NSubLongID:String;p:Pstr;bm:TBookMark;CUxLinux联盟
  beginCUxLinux联盟
   with Table1,TreeView1 doCUxLinux联盟
   beginCUxLinux联盟
  Items.BeginUpdate;CUxLinux联盟
  SetKey;CUxLinux联盟
  FieldByName('LongID').AsString:=Pstr(Node.Data)^;CUxLinux联盟
  if not GotoKey then Items.Delete(Node)CUxLinux联盟
  elseCUxLinux联盟
  beginCUxLinux联盟
   TmpNode:=Node.GetFirstChild;CUxLinux联盟
   if (TmpNode.Text=' ')and(TmpNode.Data=nil) thenCUxLinux联盟
   beginCUxLinux联盟
   TmpNode.Delete;CUxLinux联盟
   if HasSubInDbf(Node) thenCUxLinux联盟
   beginCUxLinux联盟
   NSubLongID:=FieldByName('LongID').AsString;CUxLinux联盟
   while (copy(NSubLongID,1,3)=copy(Pstr(Node.Data)^,4,3))and(not Eof) doCUxLinux联盟
   beginCUxLinux联盟
   new(p);CUxLinux联盟
   p^:=FieldByName('LongID').AsString;CUxLinux联盟
   bm:=GetBookMark;CUxLinux联盟
   TmpNode:=Items.AddChildObject(Node,FieldByName('Text').AsString,p);CUxLinux联盟
   if HasSubInDbf(TmpNode) then Items.AddChildObject(TmpNode,'',nil);CUxLinux联盟
   GotoBookMark(bm);CUxLinux联盟
   FreeBookMark(bm);CUxLinux联盟
   Next;CUxLinux联盟
   NSubLongId:=FieldByName('LongID').AsString;CUxLinux联盟
   end; end; end;CUxLinux联盟
   end;CUxLinux联盟
  Items.EndUpdate;CUxLinux联盟
   end;CUxLinux联盟
CUxLinux联盟
  end;
CUxLinux联盟
CUxLinux联盟
  以上简要谈了谈数据库的树状显示的基本方法,另外,编辑树上节点的Text属性的同时对数据库进行修改、同一数据库在多用户同时操作时数据库以及树的一致性、树上节点的拷贝与复制等就不再赘述,读者可自行完善。本文程序在Dlphi4.0、Windows 98下调试通过。CUxLinux联盟
Linux联盟收集整理 ,转贴请标明原始链接,如有任何疑问欢迎来本站Linux论坛讨论
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
 ·Delphi实现远程串口的数据采集  (2007-10-30 16:10:39)
 ·Delphi托盘编程实战演练  (2007-10-30 16:09:56)
 ·DELPHI中操作ACCESS技巧集  (2007-10-30 16:08:48)
 ·在DELPHI中打印TDBGrid内容  (2007-10-30 16:05:41)
 ·在Delphi 2005中安装组件  (2007-10-30 16:04:02)
 ·DELPHI组件安装全攻略  (2007-10-30 15:54:19)
 ·在DELPHI中用线程排序  (2007-10-30 15:41:06)
 ·Delphi的嵌入式asm: Byte快速转换为16进制  (2007-10-30 15:40:20)
 ·创建一个简单的Delphi专家  (2007-10-30 15:14:08)
 ·Delphi下的接口编程学习笔记  (2007-10-30 15:11:56)