`
ivfh
  • 浏览: 59969 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

Delphi环境下灵活的数据库树表实现

阅读更多
1 数据结构设计

  在设计时可以采用两种数据存储方式(数据结构)。

  1)信息分类表采用一个分类作为表的一条记录的方式进行存储,并由父类编号建立各类之间的关系,即:

分类号 类的含义 父类的编号

0001  计算机

0002  无线电



  2)这种分类表结构的建立不用动态生成表结构,但使用时相对麻烦。我们采用以下的表结构建立信息分类关系。这样的结构可以实现任意级的树型结构,如M层的一个结构:其中M是本单位的分类最大深度。类号要唯一识别每一个类。最上一级的分类号为全宗号+本级的分类代号,其他任意级的类其类号都为上一级的分类号+本级的分类代号。用户根据本单位档案的信息分类情况输入类信息,由系统动态创建表。

信息分类号 全宗号   类1含义   类2含义   类M含义   分类深度

0001    Zzb20    电子     计算机    2

0002    Zzb20    电子     无线电    2

0003    Zzb20    通信     卫星   

0004    Zzb20    通信     遥感


C4     C6      C20     C20     C20     C1

XXFLH   QZH      L1     L2      LM      FLSD


  在下面的例子中由于安全要求,对数据库表的结构作了简化,同时只使用了一些模拟数据以作说明。


2 树表外形设计

  由于Delphi提供的树表控件比较简单,外观不很美观,因此需要作一些“修饰”工作。为了强调重点,忽略了数据库操作如查询等,在例程中只使用了有关树表控件。

  1)增加色彩

  一般的树表控件没有底图,没有色彩,因此首先要解决色彩问题。解决的方法就是在树表控伯的ONDraw事件响应中增加底图显示代码。

procedure TForm1.Tree1CustomDraw(Sender: TCustomTreeView; const ARect: TRect; var DefaultDraw: Boolean);

begin

with tree1.Canvas do //取树表控件的显示底板

begin

brush.color:=RGB(200,200,255); //设置画笔颜色

FillRect(ARect); //填充底板
end;

end;

  这里仅为树表控件设置的底板颜色,实际上还可以设置底图,但由于底图的色彩不易控制,在调整树表结点时,容易出现颜色混乱的情况,而且只设置其颜色使树表控件的显示更加简洁。但只在ONDraw事件中设置颜色是不够的,还需要在其子项(结点)的显示事件中增加以下代码:

procedure TForm1.Tree1CustomDrawItem(Sender: TCustomTreeView;

Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);

var

Noderect:TRect;

begin

with tree1.Canvas do

begin

case Node.Level of //根据不同的层次,设置不同的结点字体颜色

0: font.Color:=clBlue;



5: font.Color:=clGreen;

end;

if node=tree1.Selected then //为突出选中的结点,将选中结点字体颜色设置为红色

font.Color:=clRed;

NodeRect:=Node.DisplayRect(false); //设置结点的显示方式

brush.Color:=RGB(200,200,255);

fillrect(NodeRect); //将结点的背景色与控件底板色设置为一致 end;

end;


2)设置图标

  图像列表控件与树表控件可以算是“老搭档”,即为了显示不同层次的结点就需要为树表控件设置一个对应的图像列表,其设置方法比较简单,可以参见有关的Delphi程序设计手册。由于树结构层次不定,因此不能象常规的方法那样建立了树表与图像列表之间的关系即大功告成,这里还需要做的是建立树表结点与图像列表的关系,可以通过以下两个函数实现。

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

begin

node.ImageIndex:=node.Level; //由结点的层次决定其对应图标在图像列表中的位置 end;


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

begin

node.SelectedIndex:=node.ImageIndex;

end;


3) 窗体激活事件响应

  响应窗体激活事件时,需要作一些设置。由于在原系统中,此窗体涉及的功能和控件较多,许多功能的完成都需要激活另外的窗体。因此需要避免对数据库信息的重复设置。可以如下实现:

procedure TForm1.FormActivate(Sender: TObject);

var

i:integer;

begin

if first_in=false then //区别是否首次激活,从而决定是否需要设置初始状态

begin

hint.Caption := ' 提示: 正在准备,请稍候...';

application.ProcessMessages ;

tree1.Items.Clear; //设置第一个树表状态和颜色

tree1.Color:=RGB(200,200,255);

tree2.Items.Clear; //设置第一个树表状态和颜色

tree2.Color:=RGB(100,200,255);

qznode:=nil; //为了显示动态结构的分类层次,将各层树结点初始化为空

for i:=0 to 5 do

last_node[i]:=nil;

stackdepth:=0; //设置栈初始深度为0

show_tree1(0); //调用show_tree1显示分类内容,参数0表示从第一层开始显示

hint.Caption:=' 提示: 数据成功调入';

Application.ProcessMessages;

end;

first_in:=true;

end;


4) 树表内容显示

  由于树表结点层次的不确定,我们采用了递归显示的方法完成树表内容的显示。这里设置了4个变量,其含义为;

变量    类型    含义      可选范围

cur_cds  TQuery   当前的查询集   dbmd.qz,dbmd.fl1,dbmd.fl2,dbmd.fl3,dbmd.fl4,dbmd.fl5

cur_str  string   当前的查询语句

num_str  String   当前的层次数查询语句

cur_level Integer   当前层次

cur_node  TTreeNode 当前结点

  这里利用栈确定父结点与子结点的关系,若某结点对应的分类深度比当前深度要大,就需要将此结点入栈,并惟此结点为父结点,以插入孩子结点方式递归地显示它的下一层结点,若当前层的结点都已显示完毕,就需要退栈,回到上一层次再作计算。主要的实现过程如下:

procedure TForm1.show_tree1(level:integer);

… //变量声明

begin

case level of //根据输入参数,确定当前数据集、结点和查询语句

0:

begin

cur_cds:=dbmd.qz;

cur_node:=qznode;

cur_str:='select distinct QZH from XXFLB ';

end;

1:

begin

cur_cds:=dbmd.fl1;

cur_str:='select distinct L1 from XXFLB ';

cur_str:=cur_str +' where QZH= '+''''+dbmd.qz.Fields.Fields[0].value+'''';

end;



end;

cur_cds.close; //实现查询

cur_cds.SQL.clear;

cur_cds.SQL.Add(cur_str);

cur_cds.open;

for i:=1 to cur_cds.RecordCount do //遍历当前层的所有结点

begin

if level=0 then //若为第一层则调用add方法创建结点

cur_node := tree1.Items.Add(cur_node,cur_cds.Fields.Fields[0].value)

else //否则,在上一结点基础上调用AddChild方法创建其子结点

cur_node:=tree1.Items.AddChild(last_node[stackdepth-1],cur_cds.Fields.Fields[0].value);

if level<5 then //根据当前结点层次及结点内容确定当前类的分类深度

begin

case level of

0:

begin

num_str:='select FLSD from XXFLB ';

num_str:=num_str +' where QZH= '+''''+dbmd.qz.Fields.Fields[0].value+'''';

end;

1:



end;

dbmd.sd.close; //执行深度查询

dbmd.sd.SQL.Clear;

dbmd.sd.sql.add(num_str);

dbmd.sd.Open;

val(dbmd.sd.Fields.Fields[0].value,cur_level,code); //取其深度

if cur_level>level then //若当前层次未达到其分类深度 begin

last_node[stackdepth]:=cur_node; //当前结点入栈

stackdepth:=stackdepth+1;

show_tree1(level+1); //递归显示下一层次结点

end;

end;

cur_cds.Next; //取当前结果集中的下一条记录

if i > cur_cds.RecordCount -1 then //若当前层中全部记录显示完毕则退栈

stackdepth:=stackdepth-1;

end;

end;

  另外第二个树表的内容显示的基本方法与此类似,所不同的是第二个树表的显示函数所带的参数为串型参数,该参数有两种可能,即为‘’或由点击第一个树表的事件产生串参数。若参数为空串,则要在第二个树表中显示所有项目,否则要根据参数创建过滤条件选择显示项目。具体方法可以参见源代码。


5) 树表调整
树表的调整即是对树表当前结点的条件,可以由两种事件产生,即树结点的扩展和点击树结点。由于一个全宗号下的分类种类很多,层次也可能很大,因此用户希望打开一个类时,与其无关的类就关闭,这样就可以保证仅有目前所选择的结点,而不需要用户利用滚动条在打开的结点中寻找。其实现要充分利用树结点的方法和属性。特别强调的是在对点击树表结点的响应事件中用到了结点的扩展方法,尽管对结点扩展事件的响应函数所实现的功能与之类似,但一定不能加入类似的结点扩展方法,如tree1.Selected.Expand(false)等,因为在扩展事件中调用扩展方法会导致事件循环,甚至死机。

对第二个树表的调整与第一个树表的处理方式类似,但功能不同,这里不多介绍。

procedure TForm1.Tree1Click(Sender: TObject);

… //变量声明

begin

if Tree1.Selected=nil then //若未选择结点,重置

begin

tree2.Items.Clear;

tree2.Refresh;

exit;

end

else

begin

tree2.Items.Clear;

tree2.Refresh;

str:=Tree1.Selected.Text; //取当前结点内容

fatherNode:=Tree1.Selected.Parent; //取当前结点父结点

tempnode:=Tree1.Selected; //设置当前结点

while fatherNode<>nil do //由当前层开始关闭所有非当前结点,

//同时返回由其第一层祖先到当前结点所组成的串,作为第二个树表显示的参数。

begin

str:=fatherNode.Text+','+str; //取父结点内容与当前结点内容联接

usenode:=fatherNode.getFirstChild; //遍历父结点的所有儿子结点

while usenode<>nil do

begin

if usenode<>tempnode then //只要不是当前结点,则取消扩展状态

usenode.Collapse(true);

usenode:=fatherNode.GetNextChild(usenode);

end;

tempnode:=fathernode; //当前层结点处理完毕后,调整父结点为当前结点

fathernode:=tempnode.Parent; //再取当前结点的父结点

end;

sibNode:=tree1.Items[0]; // 第一层结点的处理与其它层稍有差异

while sibNode<>nil do

begin

if sibNode<>tempNode then

sibNode.Collapse(true);

sibNode:=sibNode.getNextSibling;

end;

tree1.Selected.Collapse(true); //强制打开当前结点

tree1.Selected.Expand(false);

if tree1.Selected.HasChildren=false then //若当前结点无孩子,

begin

show_tree2(str); //说明已构成一个完整的类,调用show_tree2函数实现第二个树表//的内容显示,参数str为完整的类名

hint.Caption:=' 提示: 数据成功调入';

Application.ProcessMessages;

end;

end;


参考文献

1 徐新华,IDE和Object Pascal 语言,人民邮电出版社,1998.12

2 郑城荣,曾凡奎等,Delphi 运行时间库RTL和组件库VCL技术参考,人民邮电出版社,1999.1

1 徐新华,GUI编程技术,人民邮电出版社,1998.12

  • 大小: 19.4 KB
  • 大小: 12.6 KB
  • 大小: 13.2 KB
分享到:
评论

相关推荐

    Delphi中快速实现数据库树形结构并实现Treeview导航表数据

    通过以上步骤,我们可以实现一个功能完善的数据库树形结构导航系统。在实际应用中,可能还需要根据具体需求进行调整和优化,例如增加搜索功能、支持多层关联等。提供的源代码"TreeView5"可能是实现这些功能的核心...

    Delphi中快速实现数据库树形结构并实现Treeview导航表数据.rar

    "Delphi中快速实现数据库树形结构并实现Treeview导航表数据"是一个实用的技术主题,它涉及如何将数据库中的层级关系数据映射到图形化的Treeview组件上,使用户能够通过树形结构来浏览和操作数据。下面我们将深入探讨...

    DELPHI实现数据库目录树生成

    标题“DELPHI实现数据库目录树生成”涉及的是在Delphi编程环境中,使用特定技术来构建一个能够展示数据库数据的多级目录树视图。这个功能对于数据管理和浏览尤其有用,比如在文件管理系统或者数据库查询工具中,用户...

    Delphi 从数据库生成目录树

    在 Delphi 开发环境中,构建一个能够从数据库中动态生成目录树的应用程序是一项常见的任务,尤其是在数据管理和文件系统操作相关的项目中。这个标题"Delphi 从数据库生成目录树"暗示我们将利用 Delphi 的组件和...

    delphi实现myTreeView\myDBTreeView带数据库存取

    在Delphi编程环境中,`TmyDBTreeView`是一种自定义的树形视图控件,它是对标准的`TTreeView`控件的功能扩展,特别针对数据库存取进行了增强。这个控件不仅具备基本的树结构展示功能,还支持对树节点进行增、删、改的...

    Delphi读取数据库内容显示在树形视图中..rar

    本篇文章将深入探讨如何在Delphi中实现从数据库读取数据并显示在树形视图中的过程。 首先,我们需要了解Delphi中用于连接和操作数据库的基本组件。这些通常包括DBConnection、DBTable或Query组件,以及用于数据绑定...

    Delphi结合数据库演示RzTreeView树控的使用.rar

    在本文中,我们将深入探讨如何在Delphi编程环境中利用RzTreeView树形控件与数据库进行交互,同时介绍如何在程序中添加根节点和子节点。这个实例是基于Raize Components 4.3控件包,它为Delphi开发者提供了丰富的用户...

    Delphi通过SQL Server的动态树的数据查询.rar

    总结来说,"Delphi通过SQL Server的动态树的数据查询"是一个实用的技术案例,它展示了如何在Delphi环境中利用数据库的强大功能和用户友好的界面设计,实现动态的、交互式的数据查询。开发者可以通过学习和理解这个...

    Delphi 动态树结合数据库查询示例

    在Delphi编程环境中,开发人员经常需要处理用户界面的交互,特别是当涉及到数据展示时。在本示例中,我们将探讨如何使用第三方控件RzCheckTree来创建一个动态的、与数据库关联的多级树型菜单。RzCheckTree是Rad ...

    delphi 数据库操作编辑 景点编辑代码

    在Delphi编程环境中,数据库操作是开发者经常遇到的任务,特别是在构建管理系统或信息记录应用时。本主题主要聚焦于如何在Delphi中进行数据库编辑,特别是针对景点信息的管理。这里我们将探讨以下几个关键知识点: ...

    delphi7数据库编程入门捷径

    Delphi7提供了强大而灵活的数据库开发能力,主要包括两大类组件:数据访问组件(Data Access Components,简称DACs)和数据控制组件(Data Control Components)。 ##### 1. 数据访问组件(DACs) 数据访问组件...

    delphi7_myDBTreeView带数据库存取v1.5

    Delphi7作为一个经典的集成开发环境(IDE),提供了丰富的组件库来帮助开发者处理数据库相关的任务。其中,myDBTreeView组件就是一个专门为数据库设计的树形视图控件,它在Delphi7中扮演着重要的角色。本文将围绕...

    delphi7 数据库编程入门

    Delphi 7还提供了对数据库桌面(DBD)的支持,这是一个独立的数据库维护和数据定义工具,它允许开发者执行诸如查询、连接、建立和重构数据库表等操作。 #### 创建数据库 创建数据库涉及定义数据库结构,创建数据表...

    精典源码Delphi143:TTreeView组件在Delphi数据库中的应用示例.rar

    在Delphi编程环境中,TTreeView组件是一个非常重要的控件,常用于展示层次结构的数据,如文件系统、组织结构或数据库中的树形结构数据。在这个"精典源码Delphi143:TTreeView组件在Delphi数据库中的应用示例"中,...

    此为Delphi树控件的一个数据库运用.zip

    【标题】: Delphi树形控件在数据库应用中的实现 在Delphi编程环境中,树形控件(TTreeview)是一种常用的用户界面组件,它能够以层级结构展示数据,通常用于目录、文件系统或者组织结构的显示。本资源"此为Delphi树...

    TTreeView组件在Delphi数据库中的应用示例.rar

    在Delphi编程环境中,TTreeView组件是一个非常重要的控件,常用于展示层次化的数据结构,如文件系统、数据库树形视图等。本示例主要探讨如何将TTreeView与数据库结合,实现数据的动态加载和展示。以下是关于...

    Delphi结合SQL实现动态树的数据查询

    本文将深入探讨如何使用Delphi编程环境结合SQL(Structured Query Language)来实现动态树的数据查询。 首先,了解Delphi。Delphi是一款强大的Windows应用程序开发工具,它基于Object Pascal编程语言,并且集成了...

    delphi红黑树源码

    在Delphi编程环境中,理解并能正确实现红黑树对于提升程序性能和优化数据结构至关重要。 红黑树的主要特性是: 1. 每个节点要么是红色,要么是黑色。 2. 根节点是黑色。 3. 所有叶子节点(NIL或空节点)是黑色。 4....

Global site tag (gtag.js) - Google Analytics