1、我想请问如何使用数据库中的数据动态添加到TreeView中去,并分清树结构的层。如我有一根节点下面有记录,但我在显示窗体的时候不添加记录。只在点击加号的时候再动态添加数据。
2、请问数据库中的表是如何建。
以上两个问题最好有代码,有比较多的注释.谢谢!表面给100分,如回答的好。有额的分。

解决方案 »

  1.   

    楼主,给你这段代码,完全可以运行的。procedure TForm2.BitBtn1Click(Sender: TObject);
    var
      newid,oldid,jg_mc:string;
      idno:real;
      MyTreeNode1, MyTreeNode2: TTreeNode;
    begin //添加[到站油库名称]到树型目录框
      TreeView1.Items.Clear;
      
      with datamodule22.adoquery3 do
             begin
              close;
              sql.clear;
              sql.add('select * from inoilstation order by jgno');
              open;
              first;
              idno:=0;
              if recordcount >0 then
                begin   
                   newid:=FieldValues['jgno'];
                   oldid:='';
                  // MyTreeNode1 := TreeView1.Items.Add(nil, newid);
                   while not eof do
                     begin
                       with datamodule22.adoquery2 do   //根据NEWID查出表machinery中的机构名称给jg_mc变量
                          begin
                            close;
                            sql.clear;
                            sql.add('select * from machinery where jgno=:j');
                            Parameters.ParamByName('j').Value:=newid;
                            open;
                            if recordcount >0 then  jg_mc:=FieldValues['jgmc']
                            else
                              begin
                               showmessage('机构名称读不到!');
                               exit;
                              end;
                          end;
                       if newid=oldid then
                         begin
                           TreeView1.Items.AddChild(MyTreeNode1,FieldValues['dzmc']);
                           idno:=idno;
                         end
                       else
                         begin
                           idno:=idno+1;
                           MyTreeNode1 := TreeView1.Items.Add(nil, jg_mc);
                          // MyTreeNode1 := TreeView1.Items.Add(nil, newid);
                           TreeView1.Items.AddChild(MyTreeNode1,FieldValues['dzmc']);
                         end;
                       datamodule22.adoquery3.Next;
                       oldid:=newid;
                       newid:=FieldValues['jgno'];
                     end;
                end;
             end;
    end;
      

  2.   

    procedure Tfrm_gdzccggl.refresh_tree;
    var i,j:integer;
        t0,t,tt:ttreenode;
        fst,old_sydw,old_jhzt,old_xmxh:string;
    begin
      IF NOT (B_CX_JY OR B_CX_FJY) THEN EXIT;
      if rd_zcfl.ItemIndex<0 then
      begin
        messagebox(handle,'你没有足够的权限查看和维护本单位固定资产采购计划!','错误信息',mb_ok+mb_iconerror);
        exit;
      end;
      for i:=0 to componentcount-1 do
      begin
        if components[i].Tag>100 then
           (components[i] as tcontrol).enabled:=false;
      end;
      tree1.Items.BeginUpdate;
      tree1.Items.Clear;
      old_table:='-1';
      fst:=copy(get_filter(0),5,200);
      if user_info.zcbz=1 then
      begin
        t0:=tree1.Items.add(nil,'总  厂');
        t0.SelectedIndex:=0;
        t0.ImageIndex:=0;
        add_zc_child(t0);
      end
      else
      begin
        t:=tree1.Items.add(nil,user_info.dwmc);
        t.SelectedIndex:=0;
        t.ImageIndex:=0;
      end;
      q_exe.SQL.Text:='select distinct a.sydw sydw,nvl(a.jhzt,-1) jhzt,nvl(a.jhlb,''XZ'') jhlb ,B.DWXH from gdzccg_jhgl a,SYDWXXB B where  '+fst+'  AND A.SYDW=B.DWMC(+) order by B.DWXH,nvl(a.jhzt,-1)';
      q_exe.Open;
      old_sydw:='-1';
      while not q_exe.Eof do
      begin
        if old_sydw<>q_exe.FieldByName('sydw').AsString then
        begin
          old_sydw:=q_exe.FieldByName('sydw').AsString;
          old_jhzt:='-2';
          t0:=tree1.Items.add(nil,old_sydw);
          t0.SelectedIndex:=0;
          t0.ImageIndex:=0;
        end;
        if old_jhzt<>q_exe.FieldByName('jhzt').AsString then
        begin
          old_jhzt:=q_exe.FieldByName('jhzt').AsString;
          tt:=tree1.Items.addchild(t0,'['+q_exe.fieldbyname('jhzt').asstring+']'+
          ls_jhzt.strings[q_exe.fieldbyname('jhzt').asinteger+1]);
          tt.SelectedIndex:=1;
          tt.ImageIndex:=2;
        end;
        q_exe.Next;
      end;
      q_exe.close;
      tree1.Items.endUpdate;  // search_near(0);
    end;
      

  3.   

    对于这个问题来说要创建树一般要有以下的表结构:
    table(id,name,parent_id)(当然这不是唯一的结构)
    根结点的id一般为最小值。当然树的层次是固定的的话。也可以设计多个表如下:
    corp(corp_id,corp_name);
    department(corp_id,dpt_id,dpt_name);
    office(dpt_id,office_id,office_name);
    employee(office_id,emp_id,emp_name);
    corp代表公司信息表,
    department代表部门信息表,
    office代表办公室表,
    employee代表职工表,
    一个公司有多个部门,一个部门有多个办公室,一个办公室有多个职工。
    当初始化时只画出公司一层就行了。并增加一个空部门,当要onExpanded里画出部门树。。
      

  4.   

    查询数据,作个循环,每一条都tree1.Items.add一下
      

  5.   

    你首先得安排好表的设计。由于采用的是分组形式。建议有一个分组号。如第一级采用00,第二级用01第一级的下一级0000,0001等。以此类推。如现在你单击treeview1的一个分组,再点击加号,如表示为在此分组加上子分组则:treeview1.Items.AddChild(treeview1.Selected,treeview1.Selected.Text+CarGName.text);同级:则将Child去掉
      

  6.   

    创建表?
    CREATE TABLE
    创建新表。语法
    CREATE TABLE
        [ database_name.[ owner ] .| owner.] table_name
        ( { < column_definition >
            | column_name AS computed_column_expression
            | < table_constraint > ::= [ CONSTRAINT constraint_name ] }            | [ { PRIMARY KEY | UNIQUE } [ ,...n ]
        ) [ ON { filegroup | DEFAULT } ] 
    [ TEXTIMAGE_ON { filegroup | DEFAULT } ] < column_definition > ::= { column_name data_type }
        [ COLLATE < collation_name > ]
        [ [ DEFAULT constant_expression ]
            | [ IDENTITY [ ( seed , increment ) [ NOT FOR REPLICATION ] ] ]
        ] 
        [ ROWGUIDCOL]
        [ < column_constraint > ] [ ...n ] < column_constraint > ::= [ CONSTRAINT constraint_name ]
        { [ NULL | NOT NULL ]
            | [ { PRIMARY KEY | UNIQUE }
                [ CLUSTERED | NONCLUSTERED ]
                [ WITH FILLFACTOR = fillfactor ]
                [ON {filegroup | DEFAULT} ] ]
            ] 
            | [ [ FOREIGN KEY ]
                REFERENCES ref_table [ ( ref_column ) ]
                [ ON DELETE { CASCADE | NO ACTION } ]
                [ ON UPDATE { CASCADE | NO ACTION } ]
                [ NOT FOR REPLICATION ]
            ] 
            | CHECK [ NOT FOR REPLICATION ]
            ( logical_expression ) 
        } < table_constraint > ::= [ CONSTRAINT constraint_name ]
        { [ { PRIMARY KEY | UNIQUE }
            [ CLUSTERED | NONCLUSTERED ]
            { ( column [ ASC | DESC ] [ ,...n ] ) }
            [ WITH FILLFACTOR = fillfactor ]
            [ ON { filegroup | DEFAULT } ]
        ] 
        | FOREIGN KEY
            [ ( column [ ,...n ] ) ]
            REFERENCES ref_table [ ( ref_column [ ,...n ] ) ]
            [ ON DELETE { CASCADE | NO ACTION } ]
            [ ON UPDATE { CASCADE | NO ACTION } ]
            [ NOT FOR REPLICATION ]
        | CHECK [ NOT FOR REPLICATION ]
            ( search_conditions ) 
        } 抄的嘎嘎,自己翻SQL SERVER的帮助去!
      

  7.   

    例子:
    CREATE TABLE [dbo].[WAREOUTH] (
    [period] [char] (6) COLLATE Chinese_PRC_CI_AS NOT NULL ,
    [noteno] [char] (14) COLLATE Chinese_PRC_CI_AS NOT NULL ,
    [notedate] [datetime] NULL ,
    [operant] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
    [checkman] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
    [houseman] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
    [custno] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
    [PZDate] [datetime] NULL ,
    [totalcurr] [money] NULL ,
    [PayNo] [char] (3) COLLATE Chinese_PRC_CI_AS NULL ,
    [houseno] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
    [InvoiceNo] [char] (20) COLLATE Chinese_PRC_CI_AS NULL ,
    [paycurr] [money] NULL ,
    [type0] [char] (2) COLLATE Chinese_PRC_CI_AS NULL ,
    [dptno] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
    [printman] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
    [tag2] [char] (1) COLLATE Chinese_PRC_CI_AS NULL ,
    [tag1] [int] NULL ,
    [noteno1] [char] (14) COLLATE Chinese_PRC_CI_AS NULL ,
    [manager] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
    [postil] [char] (60) COLLATE Chinese_PRC_CI_AS NULL ,
    [saleman] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
    [re0] [char] (100) COLLATE Chinese_PRC_CI_AS NULL ,
    [Check1] [int] NULL ,
    [Check2] [int] NULL ,
    [Check3] [int] NULL ,
    [Man1] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
    [NoteType] [int] NULL ,
    [PZNo] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
    [InvoiceDate] [datetime] NULL ,
    [Printed] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
    [Tag3] [smallint] NULL ,
    [moddate] [datetime] NULL ,
    [modperiod] [char] (6) COLLATE Chinese_PRC_CI_AS NULL 
    ) ON [PRIMARY]
    GOALTER TABLE [dbo].[WAREOUTH] WITH NOCHECK ADD 
    CONSTRAINT [WAREOUTHPRIMARYKEY1] PRIMARY KEY  CLUSTERED 
    (
    [noteno]
    )  ON [PRIMARY] 
    GO
    在SQL SERVER当中手动创建一个表,然后生成其SQL脚本就可以看到。
      

  8.   

    表结构可以采用两种方式:
    1、编码方式,采用001001001的字符串,然后按照每级的长度切开,然后建树。这种方法最慢,而且树的层次数有限。
    2、链式存储方式。结构是 节点编号、父节点编号、名称、编码... 这种方法是最好的解决方法。我详细说一下:
    关键是两个编号字段,顶级接点的编号可以是-1或者其他特殊值(字段类型用数字或者字符串都可以)。比如树形是
    A----B
      |--C
      |--D----E
           |--F那么数据库内容是:
    节点编号 父节点编号 名称
    1         -1          A
    2         1           B
    3         1           C
    4         1           D
    5         4           E
    6         4           F
    建立树的操作可以使用一个先根顺序建立各个节点(实际上是一个递归函数,广度优先),算法如下://建立一个记录,存储树节点的信息
      PNodeData = ^TNodeData;
      TNodeData = record
        ID, ParentID: LongInt;
        Text: ShortString;
      end;//ParentTreeNode TreeView父节点
    //ParentID 父节点编号
    //TreeDataSet 存储该树的数据表、之前要打开
    procedure BuildTree(ParentNode: TTreeNode; ParentID: Integer);
    var
      I: Integer;
      ANodeData: PNodeData;
      NewNode: TTreeNode;
    begin
      //过滤出该父节点下的子节点
      TreeDataSet.Filter := Format('父节点编号 = %d', [ParentID]);
      TreeDataSet.Filtered := True;
      
      for I := 0 to TreeDataSet.RecordCount - 1 do
      begin
        ANodeData := New(PNodeData);
        ANodeData^.ID := TreeDataSet.FieldValues['节点编号'];
        ANodeData^.ParentID := TreeDataSet.FieldValues['父节点编号'];
        ANodeData^.Text := TreeDataSet.FieldValues['名称'];
        NewNode := TreeView.AddChild(ParentNode, ANodeData^.Text);
        NewNode.Data := ANodeData;
        Next;
      end;  //递归调用本函数,为各个子节点生成树
      //很明显,如果当前节点没有子节点,那么就是递归调用的结束条件了
      //这里的判断是检查第一次调用传进来的参数,如果是nil就用TreeView的属性来访问
      if Assigned(ParentNode) then
      begin
        for I := 0 to ParentNode.Count - 1 do
          BuildTree(ParentNode.Item[I], PNodeData(ParentNode.Item[I].Data)^.ID);
      else begin
        for I := 0 to TreeView.Items.Count - 1 do
          BuildTree(TreeView.Items[I], PNodeData(TreeView.Items[I].Data)^.ID);
      end;
    end;
    初始的调用方法是
    TreeDataSet.Open;BuildTree(TreeView.Add(nil, '树根'), -1);//或者 BuildTree(nil, -1);TreeDataSet.Close;
    TreeDataSet.Filter := '';
    TreeDataSet.Filtered := False;
      

  9.   

    对了,上面那段代码在程序退出的时候要记得释放每个树节点的data指针占用的内存,DELPHI不会负责释放那些空间的。如果不做,将导致内存泄露。
    再多加一点注释:
      //把数据库中查询出来的每个节点加入到ParentNode下
      for I := 0 to TreeDataSet.RecordCount - 1 do
      begin
        //为节点分配一个记录,记录节点的ID等信息
        ANodeData := New(PNodeData);
        //记录该节点的各个属性,后面要用到
        ANodeData^.ID := TreeDataSet.FieldValues['节点编号'];
        ANodeData^.ParentID := TreeDataSet.FieldValues['父节点编号'];
        ANodeData^.Text := TreeDataSet.FieldValues['名称'];
        NewNode := TreeView.AddChild(ParentNode, ANodeData^.Text);    //把该节点的DATA指针指向这个记录
        NewNode.Data := ANodeData;    //继续添加下一个节点
        Next;
      end;
      如果不执行下面的代码,那么就只生成一级的树,否则就生成全部的树。按照你的问题的要求,去掉下面的代码,在每次点一个+号的时候调用BuildTree就可以了。  if Assigned(ParentNode) then
      begin
        for I := 0 to ParentNode.Count - 1 do
          BuildTree(ParentNode.Item[I], PNodeData(ParentNode.Item[I].Data)^.ID);
      else begin
        for I := 0 to TreeView.Items.Count - 1 do
          BuildTree(TreeView.Items[I], PNodeData(TreeView.Items[I].Data)^.ID);
      end;