id    parent  caption
1     0       A
2     1       B
3     1       C
4     1       D
5     2       E
6     5       F
7     3       G

解决方案 »

  1.   

    我设计的表如下:
    Id word ParentId RootID
    1 A 0 1
    2 B 1 1
    3 C 1 1
    4 D 1 1
    5 E 2 1
    6 G 2 1
    7 F 5 1 现在的问题就是如何用Treeview控件将数据以层次的关系反应出来
      

  2.   

    我用ADOQUERY,
    表结构其实很简单
    ID SX 这是两个重要字段,其他的都不重要unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, Db, ADODB, ComCtrls;type
         tmydata=class
          node:string[3];
          parent:string[3];
          ps:real;
          name:string;
          added:boolean;
    end;
    type
      TForm1 = class(TForm)
        ADOConnection1: TADOConnection;
        Query1: TADOQuery;
        TreeView1: TTreeView;
        Button1: TButton;
        Label1: TLabel;
        Label2: TLabel;
        Query2: TADOQuery;
        procedure loaddatasfromquery;
        function addanode(adata:tmydata):ttreenode;
        procedure BuildTree;
        procedure calacanodemoney(anode:ttreenode);
        procedure Button1Click(Sender: TObject);  private
        { Private declarations }
      public  end;var
      Form1: TForm1;
      mydatas:tlist;implementation{$R *.DFM}procedure TForm1.loaddatasfromquery;
       var
         adata:tmydata;
         i:integer;
       begin
        if not assigned(mydatas) then
           mydatas:=tlist.create
        else
         begin
           for i:=0 to mydatas.count-1 do
           begin
           adata:=mydatas[i];
           adata.free;
           end;
           mydatas.clear;
        end;
        if not query1.active then query1.open;
        query1.first;
        while not query1.eof do
        begin
          adata:=tmydata.create;
          adata.node:=query1.fieldbyname('id').asstring;
          adata.parent:=query1.fieldbyname('sx').asstring;      adata.added:=false;
          mydatas.add(adata);
          query1.next;
        end;
        query1.close;
       end;     function tform1.addanode(adata:tmydata):ttreenode;
         var
           anode:ttreenode;
           i:integer;
         begin
           anode:=nil;
           if adata.added then
           begin
             anode:=treeview1.items.getfirstnode();
             while adata<>tmydata(anode.data) do
             anode:=anode.getnext();
             result:=anode;
            exit;
            end;
           if trim(adata.parent) <>'' then
             for i:=0 to mydatas.count-1 do
              if tmydata(mydatas[i]).node=adata.parent then
               begin
                anode:=addanode(tmydata(mydatas[i]));
                break;
               end;
           result:=treeview1.items.addchildobject(anode,adata.node,adata);
           adata.added:=true;
         end;procedure TForm1.BuildTree;
    var
      i : integer;
    begin
      TreeView1.Items.BeginUpdate;
      TreeView1.Items.Clear;
      LoadDatasFromQuery;
      for i := 0 to MyDatas.Count - 1 do
        if not TMyData(MyDatas[i]).Added then AddANode(MyDatas[i]);
      TreeView1.Items.EndUpdate;end;procedure TForm1.calacanodemoney(anode:ttreenode);
      var
        achild:ttreenode;
        adata,cdata:tmydata;
        scale:real;
       begin
        adata:=anode.data;
           case(anode.level) of
            1: scale:=20;
            2: scale:=5;
            3: scale:=5;
            4: scale:=5;
            5: scale:=10;
            end;
            achild:=anode.getfirstchild;
            while achild<>nil do
            begin
              if achild.haschildren then calacanodemoney(achild);
              query1.open;
               if Query1.Locate('ID',VarArrayOf([adata.node]),[]) then
               begin
                    Query1.Edit;
                    Query1.FieldByName('Ps').asfloat:=adata.ps;
            Query1.post;
               end;
               achild:=achild.getnextsibling;
      end;
      end;procedure TForm1.Button1Click(Sender: TObject);
    var
      aNode : TTreeNode;
      begin
      BuildTree;
        aNode:=TreeView1.items.getfirstnode;//找到第一个顶结点
      // if Assigned(aNode) then ShowMessage(aNode.text);
       showmessage(anode.text);
       while Assigned(aNode) do
       begin
         if aNode.HasChildren then CalacANodeMoney(aNode);
         end;
    end;end.
      

  3.   

    ID NAME PARENT 
    递归建树,我程序里的,希望你能看的懂:
    procedure TMDIChild.LoadTreeView;
    var
      strsql,tid:string;
    begin
      try    DataModule3.ADOTable3.open;
        DataModule3.ADOTable3.Locate('DTname',RzComboBox1.Text,[lopartialkey]);
        tid:=inttostr(DataModule3.ADOTable3.FieldByName('id').value);
        strsql:='select * from T where TypeID='+tid;
        DQ.Active :=false;
        DQ.SQL.Clear ;
        DQ.SQL.Add(strsql);
        DQ.Active :=true;
        DQ.Filtered :=true;
        DQ.Filter := 'Parent=0';
        U_DiGui(0,RzTreeView1.TopItem );//从当前0层开始递归建树
      except
        showmessage('字典里没有数据!');
      end;
    end;
    procedure TMDIChild.U_DiGui(parentID:Cardinal;ParentNode:TTreeNode);
    var
      tmpTBData:array of TableData;
      i,j:integer;
      tmpNode:TTreeNode;begin
      j:=DQ.RecordCount;
      setlength(tmpTBData,j);//保存递规上一层结点值
      for i:=0 to j-1 do begin
        tmpTBData[i].ID := Cardinal(DQ.fieldbyname('ID').value);
        tmpTBData[i].Name  := DQ.fieldbyname('Name').value;
        tmpTBData[i].ParentID  := Cardinal(DQ.fieldbyname('Parent').value);
        DQ.Next;
      end;
      for i:=0 to j-1 do begin //递规调用建立所有结点
        tmpNode:=RzTreeView1.Items.AddChild(ParentNode,tmpTBData[i].Name);
     //   tmpNode.ImageIndex:=2;
        new(pData);
        pData^.ID:=tmpTBData[i].ID;
        tmpNode.Data:=pData;
        DQ.Filter := 'Parent=' + IntToStr(Integer(tmpTBData[i].ID));
        if DQ.RecordCount >0 then begin
          U_DiGui(tmpTBData[i].ID,tmpNode );
        end;
      end;
    end;
      

  4.   

    create table TableTree (TreeText text); /* 这是我设计的表 *///参考
    TTreeView.SaveToStream();
    TTreeView.LoadFromStream();
      

  5.   

    呵呵,这么多高手回答了.
    仅仅显示ID NAME PARENT 三个字段是最好的设计.
    如果为了其他地方的方便,可以考虑加"所在的层次","根ID"两个字段,看需要.
      

  6.   

    呵呵,这么多高手回答了.
    仅仅显示ID NAME PARENT 三个字段是最好的设计.
    如果为了其他地方的方便,可以考虑加"所在的层次","根ID"两个字段,看需要.
      

  7.   

    数据表结构用的是 netlib(河外孤星)  的方法,
    在添加节点的时候将表中的数据按照 parentid 排序返回记录集,添加的每一个
    ID保存在TTreeNode的Data属性中。
      

  8.   

    建表,可以按照你自已的想法建。
    用TreeView来实现,也不难,你记得保存自已的父结点.
      

  9.   

    用cg1120的递归算法比较好;
    记得不要每次更新的时候都重画树;
    表的结构中画树只需要两个字段,一个标志其本身的ID,另外一个标志她的上级节点的ID,根节点的上级赋一个特殊的值
      

  10.   

    我用的是排序字段,数据少的用INT,数据多的只好用VarChar,第一层节点 第二层节点 ... 第N层节点关键技术是用SQL按该字段排序后,可以直接用树的绝对编号。
    以后在记录定位时只要用MoveBy(n),查询速度也很理想。所做过的树数据实例是把一辆火车逐级分解成另件,至少有一万条记录,只是在读入时有等待,其它操作都正常。