• 我们以建立一个城市名称的树形结构为例来说明如何快速生成树形并实现导航数据表。


    1. 先建立编码表:city_tree(bianma,cityname)。
    2. 新建一个项目,按默认保存。
    3. 新建一公共单元pubvar,在其中定义以下常量:
    Const
    cTreeCodeFormat = ‘222’;//编码格式为 XX XX XX
    cTreeMaxLevel = 3;//最大编码层次
    cTreeRootTxt = ‘城市’;//树根结点名称
    这样做为了提高程序的通用性,以后用于其他代码字典的维护时,只需要更改这些特征常量。
    4. 程序源代码:
    unit Unit1;
    interface
    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DB, DBTables, ImgList, ComCtrls , PubVar, Grids, DBGrids, Menus , StrUtils, StdCtrls;

    type
    TForm1 = class(TForm)
    Tree: TTreeView;
    ImageList1: TImageList;
    Table1: TTable;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    PopupMenu1: TPopupMenu;
    AddMenu: TMenuItem;
    DeleteMenu: TMenuItem;
    RenameMenu: TMenuItem;
    Query1: TQuery;
    DataSource2: TDataSource;
    procedure AddMenuClick(Sender: TObject);//点击增加子项菜单
    procedure RenameMenuClick(Sender: TObject);//点击重命名菜单
    procedure DeleteMenuClick(Sender: TObject); //点击删除该项菜单
    procedure FormCreate(Sender: TObject);
    procedure TreeClick(Sender: TObject);
    private
    { Private declarations }
    public
    { Public declarations }
    procedure LoadTree(treeDB:TDBDataSet);//初始化树
    procedure UpdateTree(curNode:TTreenode; nodeTxt:string; state:string);//更新树
    function GetNodeLevel(sFormat,sCode:string):integer;//获得节点层数
    function GetCurrChildNodeMaxMa(curNode:TTreenode):string;
    //获得当前节点子节点的最大编码
    function GetCurrentNodeBianma(curNode:TTreenode):string;//获得当前节点的编码
    procedure UpdateTable(bianma:string; cityname:string ;state:string); //更新数据库
    end;

    var
    Form1: TForm1;
    CurrentTreeNode: TTreeNode;
    // AddChildeTreeNode: TTreeNode;
    // flag:boolean; //用于标识是否需要在重命名树结点时更新数据

    implementation
    uses AddChildUnit,RenameItemUnit;
    {$R *.dfm}

    procedure TForm1.LoadTree(treeDB:TDBDataSet);//初始化树
    var
    curID,nodeTxt:string;
    level:integer;
    mynode:array[0..3] of TTreenode;
    begin //初始化变量
    Screen.Cursor:=crHourGlass;
    tree.Enabled:=True;
    tree.Items.Clear;
    level:=0 ;
    //设置根节点
    mynode[level]:=tree.items.add(Tree.Topitem,cTreeRootTxt);
    mynode[level].ImageIndex:=1;
    //遍历数据表,利用编码字段记录排序规律,依次添加树节点
    with treeDB do
    begin
    try
    if not Active then open;
    first;
    while not Eof do
    begin
    curID:=trim(FieldByName('bianma').AsString);
    nodeTxt:=curID+'-'+trim(FieldByName('cityname').AsString);
    level:=GetNodeLevel(cTreeCodeFormat,curID);
    //这里返回代码的层次数
    if level>0 then
    begin
    //增加下一节点时,用添加子节点的方法可轻松实现节点间的层次关系
    //注意:这里的父节点是用当前节点的上一级节点mynode[level-1]
    mynode[level]:= tree.items.addchild(mynode[level-1],nodeTxt);
    mynode[level].ImageIndex:=2;
    end;
    next;//下一条记录
    end;
    finally
    close;
    End;
    mynode[0].expand(False);
    Screen.Cursor:=crDefault;
    end;
    end;

    function TForm1.GetNodeLevel(sFormat,sCode:string):integer;//获得节点层数
    var i,level,iLen:integer;
    begin
    level:=-1 ;
    iLen:=0;
    if (sFormat<>'') and (sCode<>'') then
    for i:=1 to Length(sFormat) do //分析编码格式,找出当前代码层次
    begin
    iLen:=iLen+StrToInt(sFormat);
    if Length(sCode)=iLen then
    begin level:=i; break; end;
    end;
    result:=level;
    end;

    //以下过程在新增、删除、修改记录时,同步更新树形结构
    procedure TForm1.UpdateTree(curNode:TTreenode; nodeTxt:string; state:string);
    Begin
    if UpperCase(state)='ADD' then
    begin
    curNode:=tree.items.addchild(curNode,nodeTxt);
    curNode.ImageIndex:=2;
    end;
    if UpperCase(state)='DEL' then
    begin
    curNode.DeleteChildren;
    curNode.delete;
    end;
    if UpperCase(state)='EDI' then curNode.Text:=nodeTxt;
    end;

    procedure TForm1.AddMenuClick(Sender: TObject);//点击增加子项菜单
    var AddChildText, AddTableText,maxbianma : string;
    begin
    AddChildForm.Label1.Caption:='为&quot;'+CurrentTreeNode.Text+'&quot;增加子项 ';
    if AddChildForm.ShowModal=mrOk then
    begin
    AddChildText:=AddChildForm.Edit1.Text;
    maxbianma:=GetCurrChildNodeMaxMa(CurrentTreeNode);
    if (CurrentTreeNode.Text='城市') and (maxbianma='1000') then
    maxbianma:='11'//如果当前节点为根节点,且只有一个子节点,使增加节点编码为11
    else if CurrentTreeNode.Text='城市' then
    maxbianma:=IntToStr(StrToInt(LeftStr(maxbianma,2))+1)
    else
    maxbianma:=IntToStr(StrToInt(maxbianma)+1); //使子项编码自动增1
    if maxbianma<>'0' then
    begin
    //增加树子层
    AddTableText:=maxbianma+'-'+AddChildText;
    UpdateTree(CurrentTreeNode,AddTableText,'add'); //更新树
    UpdateTable(maxbianma,AddChildText,'add'); //更新表
    ShowMessage('添加成功!');
    end
    else ShowMessage('此层为最低子层,不能在该层增加子层');
    AddChildForm.Edit1.Text:='';
    end;
    end;

    function TForm1.GetCurrChildNodeMaxMa(curNode:TTreenode):string;
    //获得当前节点子节点的最大编码
    var
    aSQL,maxbianma:string;
    li_pos:integer;
    begin
    li_pos:=pos('-',curNode.Text);
    if li_pos=7 then
    begin result:='-1'; exit; end;
    if (li_pos=0) and (not(curNode.HasChildren)) then // 如果当前节点为根节点并且没有子节点
    begin
    result:='9'; //使根节点第一个节点编码为10
    exit;
    end
    else begin
    aSQL:='select bianma from city_tree where bianma like &quot;' + MidStr(curNode.Text, 1, li_pos-1) + '%&quot;';
    Query1.UnPrepare;
    Query1.Close;
    Query1.SQL.Clear;
    Query1.SQL.Text:=aSQL;
    Query1.Prepare;
    Query1.ExecSQL;
    Query1.Active:=true;
    Query1.Last;
    maxbianma:=Query1.fieldbyname('bianma').AsString;
    if Query1.RecordCount=1 then//如果当前项没有子项
    maxbianma:=maxbianma+'00';
    Query1.Active:=false;
    end;
    result:=maxbianma;
    end;

    procedure TForm1.RenameMenuClick(Sender: TObject);//点击重命名菜单
    var
    bianma:string;
    itemtext:string; //用于重命名时保存输入的Edit.text
    begin
    RenameItemForm.Label1.Caption:='将&quot;'+CurrentTreeNode.Text+'&quot;命名为 ';
    if RenameItemForm.ShowModal=mrOk then
    begin
    itemtext:=RenameItemForm.Edit1.Text;
    bianma:=GetCurrentNodeBianma(CurrentTreeNode);
    Table1.Locate('bianma',bianma,[]);
    UpdateTable('',itemtext,'edi');
    itemtext:=bianma+'-'+itemtext;
    UpdateTree(CurrentTreeNode,itemtext,'edi');
    ShowMessage('重命名成功!');
    end;
    end;
    //以下过程在新增、删除、修改记录时,同步更新数据库表
    procedure TForm1.UpdateTable(bianma:string; cityname:string ;state:string); //更新数据库
    begin
    if state='add' then
    begin
    Table1.Active:=True;
    Table1.Insert;
    Table1.SetFields([bianma,cityname]);
    Table1.Post;
    end;
    if state='del' then
    begin
    Table1.Active:=True;
    Table1.Locate('bianma',bianma,[]);
    Table1.Delete;
    end;
    if state='edi' then
    begin
    Table1.Edit;
    Table1.FieldByName('cityname').AsString:=cityname;
    Table1.Post;
    end;
    end;

    procedure TForm1.DeleteMenuClick(Sender: TObject); //点击删除该项菜单
    var
    bianma:string;
    begin
    CurrentTreeNode.expand(False);
    if CurrentTreeNode.Text='城市' then //如果当前节点为根节点
    begin
    ShowMessage('不能删除根节点');
    exit;//退出该过程
    end;
    if CurrentTreeNode.HasChildren then //如果当前节点具有子项
    begin
    ShowMessage('请先删除其子项');
    exit;//退出该过程
    end;
    if Application.MessageBox(PChar('真的要删除&quot;'+CurrentTreeNode.Text+'&quot;这项吗?'),'警告',MB_YESNO)=mrYES then
    begin
    bianma:=GetCurrentNodeBianma(CurrentTreeNode);
    UpdateTree(CurrentTreeNode,'','del');
    UpdateTable(bianma,'','del');
    ShowMessage('删除成功!');
    Table1.Refresh;//更新TBGrid控件中的显示
    Table1.Active:=true;
    CurrentTreeNode:=Form1.tree.selected;
    end;
    end;

    function TForm1.GetCurrentNodeBianma(curNode:TTreeNode):string;//获得当前节点的编码
    var
    li_pos:integer;
    bianma:string;
    begin
    li_pos:=pos('-',curNode.Text);
    bianma:=MidStr(curNode.Text,1,li_pos-1);
    result:=bianma;
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    LoadTree(Table1);
    Table1.Active:=true;
    end;

    procedure TForm1.TreeClick(Sender: TObject);
    begin
    CurrentTreeNode:=Form1.tree.selected; //获得当前节点
    end;

    end.

    unit PubVar;
    interface
    uses
    SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, DbTables, StdCtrls, ExtCtrls, Buttons, Dialogs,Registry,Db, ComCtrls;

    const
    cTreeCodeFormat='222'; //编码格式:xx xx xx
    cTreeMaxLevel=3; //最大编码(树节点)层次
    cTreeRootTxt='城市'; //树的根节点名称
    implementation
    end.

    好的代码像粥一样,都是用时间熬出来的
  • 相关阅读:
    Introduction to Guid ( globally unique identifier )
    Visual Studio调试技巧 -- Attach to Process #Reprinted#
    ASP.NET PipeLine #Reprinted#
    Introduction to REST #Reprinted#
    HTTP status codes
    Introduction to Json
    Visual Studio shortcut keys
    C# Programming Study #1
    面向对象程序设计-C++ Finial exam review NOTES【第十六次上课笔记】
    几道汇编入门题目(二)
  • 原文地址:https://www.cnblogs.com/jijm123/p/13388623.html
Copyright © 2020-2023  润新知