前往Shuct.Net首页

Shudepb PB反编译专家长时间以来,为业内同类软件事实上的唯一选择.细节,彰显专业.态度,决定品质.

关于PowerBuilder的搜索

PowerBuilder中实现并应用树形视图 ---     在PowerBuilder中实现并应用树形视图 吴惠民··yesky 应用与开发 树形视图控件最适合显示具有层次关系的数据,在Windows9x/2k中文件和文件夹(子目录)之间的关系就是用树形视图来表现的。在数据库中,树形视图是管理大量数据的好方法,因为用户只需简单地点击鼠标就可以选择自己需要的数据。   当我们对数据的表现有以下要求时,我们可首先考虑使用树形视图控件:    * 显示层次结构中元素之间的关系;    * 元素在层次结构之间漫游(元素间的拷贝、移动等);    * 描述每个元素相关信息;    * 将大量数据检索的过程划分为若干步骤,只表现其中需要的部分。   在PowerBuilder中,对树形视图的编程是窗口中较为复杂的部分,它无法像数据窗口那样使用一条Retrieve()函数就可以将数据表现出来。下面我们结合树的数据结构及其存储和遍历,探讨一下树形视图的构建和应用。   1. 树的数据结构及其存储结构   树是一种常见的非线性的数据结构,使用非常广泛。一般人们用孩子表示法、孩子兄弟表示法(二叉树表示法)和双亲表示法来存贮一棵树。其中前两种表示法或因各结点不同构或冗余度太大,或因存贮量太大而不适合在PowerBuilder中应用,而数据库中表的结构和特性正与树的双亲结点表示法的要求相符合,因而最好是采用双亲节点表示法。   树的双亲节点表示法利用了每个节点(除根节点外)只有唯一的双亲的性质,每个结点的结构分为两个域,即Data域和Link域。Data域用以存储本节点的有关信息,Link域为指向双亲节点的指针。   2.数据库中表的设置   为了便于说明问题,我们以商品传销网为例,传销网中每个人都对应到树中的一个节点。我们把有关数据存储在表Persons中。   根据树的双亲节点表示法的特点,同时考虑到便于查询,将Data域分成本人代号(code)和本人姓名(name)两个字段,而Link域对应到上线代号字段(pcode)。虽然在关系型数据库中,数据的操作是以集合为基础的,而集合中的元素是没有顺序的,但在构建树形视图时必须一个一个地将节点添加进去,且PowerBuilder不支持指针型变量,因而我们在表Persons中增加一字段Handno,记录每个结点的句柄,配合Pcode字段,以实现"指针"的功能,其原理是:通过查找本结点的上线代号来查找其双亲结点的句柄号。由于树形视图等级结构非常明显,我们采用按层次遍历树,所以我们在Persons表中再增加一个字段Grade,便于按层次顺序构建树形视图。表Persons的结构如下表,主键为code列。当然可在表中设置一个或多个字段,以存储各结点的其他信息,但本文旨在说明问题,故不予考虑。   表Persons的结构如表1所示。   表1 Persons表的结构 Column Name Data Type Width Null Dec Default 字段含义 Code Char 8 No 代号 Name Char 8 No 姓名 Pcode Char 8 Yes 上线代号 Grade Integer No 1 层次 Handno Numeric 20 0 Yes 1 句柄号  3.树形视图结构分析   在PowerBuilder中树形视图控件包括了树形视图(TreeView)和树形视图项(TreeViewItem)两个对象。其中树形视图对象可以在窗口画笔中通过点击鼠标的方式创建,而树形视图项则必须通过编程来声明及定义它们的属性。   在窗口画笔中用鼠标在窗口上放置了一个树形视图的控件后,可以认可将在窗口的这个位置采用树形视图来表现的一些信息;还可以通过设置这个控件的属性确定它是否可见、是否显示连线等基本属性。而这时运行这个窗口,看到的只是这个树型控件的空架子,其中没有任何数据。 树型控件的每一个数据项都是一个TreeViewItem,而这些树形视图项只能在程序中逐项加入。   将树形视图项加入到树形视图中的方法是使用InsertItem()系列函数中的一种,其中:    ·InsertItemFirst()将加入项作为第一个子项;    ·InsertItemLast()将加入项作为最后一个子项;    ·InsertItem()将加入项放在指定的子项后面;    ·InsertItemSort()按排序的顺序放置加入项。   4.树形视图(TreeView)和树形视图项(TreeViewItem)对象的常用属性   (1)树形视图项(TreeViewItem)对象的常用属性     ---- Label:String 型,树形视图项的显示信息。     ---- Data:Any型,树形视图项的内部值。     ---- Level:Integer型,树形视图项在树形视图中级别。     ---- Children:Boolean 型,它决定该项是否有下一层(如图1中书名)。     ---- PictureIndex:Integer 型,该项非选中时所用的图标在图标队列中的编号。     ---- SelectedPictureIndex:Integer型,该项选中时所用的图标在图标队列中的编号。   (2)树形视图(TreeView)控件的常用属性     ---- Picture:在Picture Name中加入四个不同的图标,用于代表树形视图中的两个层次(一、二级)、两种状态(未选、选中)。     ---- General:可根据具体应用设定是否选中,其中:     ---- DeleteItems:运行中是否允许删除表项。     ---- DisableDragDrog: 运行中是否允许拖放表项。     ---- EditLabels: 运行中是否允许单击表项来改变表项的标题。     ---- ShowButtons:是否在表项放显示+-按钮,有示相对的扩展和收缩。     ---- HideSelection:当该控件失去焦点时,选中项是否以高亮度显示。     ---- ShowLine:表项间是否加一竖线。     ---- LinesAtRoot:所有根层表项是否用竖线连接。     ---- Indentation:子表项相对于父表项的向右缩进度。   5.应用举例   为了从表中选取数据,我们又定义了两个数据窗口对象dw_persons_code和dw_persons_grade,它们的检索条件分别为persons.code=:mycode和persons.grade=:mygrade,其中mycode和mygrade分别为字符串型和整型检索变量。   在PowerBuilder的应用中,我们可建立窗口w_treeview,在此窗口中对树形视图对结点进行增加、删除、修改等操作。在w_treeview中,建立一个树形视图控件tv_1,以及三个数据窗口控件dw_1、dw_2和dw_3,其中dw_1与数据窗口对象dw_persons_code相关联,另两个数据窗口控件均与数据窗口对象dw_persons_grade相关联。另外,我们还定义了几个共享变量,其定义如下: treeviewitem tvitem,tvitem1 long handleno string mcode,mname   为了在打开窗口w_treeview时即可看到树形视图,可为w_treeview窗口的open事件编写如下脚本: long newitem, rootitem int rowcount1, rowcount2, grade1, i, j, k string code1, name1 connect; dw_1.settransobject(sqlca) dw_2.settransobject(sqlca) dw_3.settransobject(sqlca) dw_1.visible=false dw_2.visible=false dw_3.visible=false select max(grade) into :grade1 from persons; tv_1.setredraw(false) select code into :code1 from persons where grade=1; file://根节点只有一个 i=dw_1.retrieve(code1) tvitem.label="(1)"+dw_1.getitemstring(1,"code")+"/" +dw_1.getitemstring(1,"name") tvitem.pictureindex=1 tvitem.selectedpictureindex=1 rootitem=tv_1.insertitemlast(0,tvitem) file://建立根节点 dw_1.setitem(1,"handno",rootitem) file://存贮根节点句柄 dw_1.update() for i=2 to grade1 step 1 dw_3.retrieve(i) rowcount2=dw_3.rowcount() dw_2.retrieve(i - 1) rowcount1=dw_2.rowcount() for j=1 to rowcount1 step 1 rootitem=dw_2.getitemnumber(j,"handno") file://取双亲节点句柄号 code1=dw_2.getitemstring(j,"code") for k=1 to rowcount2 step 1 mcode=dw_3.getitemstring(k,"pcode") if mcode=code1 then name1=dw_3.getitemstring(k,"name") tvitem.label='('+string(i)+")"+code1+'/'+name1 tvitem.pictureindex=2 tvitem.selectedpictureindex=4 newitem=tv_1.insertitemsort(rootitem,tvitem)//插入新节点 dw_3.setitem(k,"handno",newitem) file://存贮新节点的句柄号 end if next next dw_3.update() next tv_1.setredraw(true) rootitem=tv_1.finditem(roottreeitem!,0) tv_1.expandall(rootitem) file://展开树形视图 tv_1.setfocus() 6.几点说明   (1)用此方法可生成并管理任意层次的树形视图,每个节点的label属性记录了各个人员的代号、姓名及在整个传销网中的层次,十分直观,且操作方便,易于扩展其他功能。另外,可根据该树的节点的多少,调整表persons的handno字段的长度。   (2)一般来讲,当数据量很小而且数据间没有复杂的关系时,可以在树形视图创建时就预先直接把各项加入到树形视图中。而数据较多时,则根据需要来制定树形视图,不要制定整个树形视图控件的每一层的每一项,而是将用户检索数据的过程划分为若干步骤,只是在用户打开一个具体的树形视图项时,才根据用户的需要检索数据,展开该节点下的各个子树分支。另外,我们在操作时往往只关心其中部分节点的信息,没有必要同时将所有子结点都展开显示。这样可减少初始化树形视图的时间,提高显示数据的效率。 在制定时,可以在某一项被选中时制定该项的下一层,也可以制定该项的下两层。第二种方法可以保证打开按钮与数据同步。 由于没有填充所有节点,我们可编程对数据库或表进行检索,判断各结点有没有子结点,并在该结点前显示不同的图标加以区分,以便于操作。   (3)在这里,表persons需要初始化,即必须在构建树形图前必须输入根节点的本人代号、本人姓名及层次等信息。树形图构建好之后,向表中添加记录时,字段grade的值可由该结点的level属性的值来确定,所以在编和对树形视图做增加、删除或修改等操作时,应注意对表persons的有关字段的值的维护。   (4)可以利用拖放技术实现TreeView中各层数据之间的移动、复制等功能,完善应用程序,本文不再赘述。----  (摘自计算机世界网) 版权信息: 本主页版权所有:北京师范大学现代教育技术研究所;管理员信箱:ysq@elec.bnu.edu.cn;电话:010-62206922。要获取最佳浏览效果,请使用800*600分辨率模式。