Oracle Form Builder中使用树的心得

oracle|心得

一、树的简介
Developer 6.0以上版本提供了hierarchy tree(层次树)的概念,htree控件非常方便,只需要少量的编程即可实现显示层次结构的目的。

 

树的特有属性中如下几个较为重要:

l         多项选择(Multi-Selection):是否允许一次选中树的多个节点。如果不允许,那么              选中第二个节点时,第一个被选中的节点会取消选择。

l         记录组(Record Group):指定生成树的记录组的名字。

 

简单介绍一下跟树相关的触发子(Built-in):

l         FUNCTION GET_TREE_NODE_PROPERTY (item_name VARCHAR2, node NODE,   property NUMBER);

功能:取得树节点的属性

其中property有如下几种:

NODE_STATE:EXPANDED_NODE(扩展节点)

COLLAPSED_NODE(收缩节点)

LEAF_NODE(叶节点)--注:不能展开或收缩

NODE_DEPTH:既节点在树中的层级。

NODE_LABEL:节点的显示文本

NODE_ICON:节点的图标

NODE_VALUE:节点的值。

例子:

DECLARE

   htree         ITEM;

   node_value    VARCHAR2(100);

BEGIN

   -- 得到树

   htree := Find_Item('tree_block.htree3');

   -- 得到当前选中节点的值

   node_value := Ftree.Get_Tree_Node_Property(htree, :SYSTEM.TRIGGER_NODE, Ftree.NODE_VALUE);

   ...

END;

注释:其中: SYSTEM.TRIGGER_NODE指当前选中的树节点。

l         FUNCTION GET_TREE_PROPERTY (item_name VARCHAR2,property NUMBER);

功能:取得树的属性

其中property有如下几种:

DATASOURCE

RECORD_GROUP

QUERY_TEXT

NODE_COUNT:返回树中节点的个数。

SELECTION_COUNT

ALLOW_EMPTY_BRANCHES

ALLOW_MULTI-SELECT

l         PROCEDURE SET_TREE_NODE_PROPERTY (item_name VARCHAR2,node FTREE.NODE,property NUMBER,value VARCHAR2);

功能:设置树节点的属性

l         PROCEDURE SET_TREE_PROPERTY (item_name VARCHAR2,property NUMBER, value VARCHAR2);

PROCEDURE SET_TREE_PROPERTY (item_name VARCHAR2,property NUMBER, value RECORDGROUP);

功能:设置树的属性

l         PROCEDURE POPULATE_TREE (item_name VARCHAR2);

功能:清空树中已有数据,并根据记录组或数据查询重新生成树。

l         PROCEDURE ADD_TREE_DATA (item_name VARCHAR2,node FTREE.NODE, offset_type NUMBER,offset NUMBER,data_source NUMBER,data VARCHAR2);

功能:在指定节点下添加树中数据

注:使用比较麻烦。

l         FUNCTION FIND_TREE_NODE(item_name VARCHAR2,earch_string VARCHAR2,   search_type NUMBER,search_by NUMBER,search_root NODE,start_point NODE);

功能:找到显示文本或值符合search_string的节点。

参数:

search_type:FIND_NEXT

            FIND_NEXT_CHILD

Search_by:NODE_LABEL

          NODE_VALUE

Search_root:查询的根节点,一般是Ftree.ROOT_NODE

Start_point:查找的开始节点,一般是Ftree.ROOT_NODE

l         FUNCTION ADD_TREE_NODE(item_name VARCHAR2,node FTREE.NODE,   offset_type NUMBER,offset NUMBER,state NUMBER,label VARCHAR2, icon VARCHAR2,value VARCHAR2);

功能:添加树节点。

Offset_type:指定节点的分支类型,PARENT_OFFSET和SIBLING_OFFSET

Offset:指定新节点的位置,

PARENT_OFFSET:1..N

                         LAST_CHILD

SIBLING_OFFSET:NEXT_NODE

                         PREVIOUS_NODE

State:EXPANDED_NODE(扩展节点)

COLLAPSED_NODE(收缩节点)

LEAF_NODE(叶节点)

l         PROCEDURE DELETE_TREE_NODE(item_name VARCHAR2,node NODE);

功能:删除树节点

l         FUNCTION GET_TREE_NODE_PARENT(item_name VARCHAR2,node NODE);

功能:得到指定节点的父节点。

l         FUNCTION GET_TREE_SELECTION(item_name VARCHAR2,selection NUMBER);

功能:得到处于选中状态的节点。

l         PROCEDURE SET_TREE_SELECTION(item_name VARCHAR2,node NODE, selection_type NUMBER);

功能:指定单个节点的选中状态

参数:

selection_type:SELECT_ON

             SELECT_OFF

             SELECT_TOGGLE

 

FORM运行态时有关的触发器:

l         When-Tree-Node-Activated:用户双击节点或在节点选中时按[ENTER]键时触发。

l         When-Tree-Node-Expanded:节点展开或收缩时触发

l         When-Tree-Node-Selected:当节点选中或取消选择时触发
二、生成树的方式
树控件一般单独放在一个控制块中(注:不能放在数据块中),在画布(CANVAS)上放置树很容易,并且,如无必要,树的属性也不需要设置。

 

生成树的方式有几种:

l         运行前通过设置记录组或数据查询属性来生成

l         通过ADD_TREE_DATA触发子来实现

l         运行态,通过ADD_TREE_NODE等触发子来实现

l         运行态,通过添加或删除记录组的数据元素来实现

 

分析:

一、 对树直接操作

描述:Find_Tree_Node找到指定节点,Add_Tree_Node来添加其下级节点。

缺点:编程较为复杂,操作不灵活,而且易出错。

优点:可以对添加节点等过程进行控制,实现一些特殊要求。

例子:

   --dept_cur为取单位的CURSOR,emp_cur为取雇员的CURSOR

   htree := Find_Item('tree_view.tree_emp');

   open dept_cur;

   loop

   fetch dept_cur into aa;

   exit when dept_cur%notfound;

   del_node := Ftree.Find_Tree_Node ( htree,aa.kjmc, Ftree.FIND_NEXT, Ftree.NODE_LABEL, Ftree.ROOT_NODE, Ftree.ROOT_NODE);

   -- 删除单位节点及其子节点

   IF NOT Ftree.ID_NULL(del_node) then

      Ftree.Delete_Tree_Node(htree, del_node);

   END IF;

   end loop;

   close dept_cur;

 

   -- 根据用CURSOR取得的单位生成树的第一层节点

   open dept_cur;

   loop

   fetch dept_cur into aa;

   exit when dept_cur%notfound;

   new_node := Ftree.Add_Tree_Node(htree, Ftree.ROOT_NODE, Ftree.parent_OFFSET, Ftree.LAST_CHILD, Ftree.EXPANDED_NODE, aa.dname, '', aa.deptno);

   end loop;

   close dept_cur;

   --根据雇员CURSOR生成树的下层节点

   open emp_cur;

   loop

   fetch emp_cur into bb;

   exit when emp_cur%notfound;

      find_node := Ftree.Find_Tree_Node(htree, bb.kjbh, Ftree.FIND_NEXT,

                 Ftree.NODE_value, Ftree.ROOT_node, Ftree.ROOT_NODE);

      new_node := Ftree.Add_Tree_Node(htree, find_node, Ftree.parent_OFFSET, Ftree.LAST_CHILD, Ftree.EXPANDED_NODE, bb.ename, '', bb.empno);

   end loop;

   close emp_cur;

   -- 得到树的根节点

   ss := Ftree.get_tree_property(htree,FTREE.NODE_COUNT);

   -- 循环,直到树的所有节点都展开

   for j in 1..ss LOOP

      exp_node  := Ftree.Find_Tree_Node(htree, '');

      state := Ftree.Get_Tree_Node_Property(htree, j, Ftree.NODE_STATE);

      IF state = Ftree.COLLAPSED_NODE THEN

         Ftree.Set_Tree_Node_Property(htree, j, Ftree.NODE_STATE, Ftree.EXPANDED_NODE);

      END IF;

   END LOOP;

二、 动态记录组

层次树所使用记录组的数据格式:

  +  — Car

  |

  -  — Airplane

     | — Boeing

     | — Boeing

 

初始状态

层数

显示文本

图标

-1(收缩节点)

1

‘Car’

''

‘car’

0(叶节点)

2

'Honda'

''

'civic'

1(展开节点)

1

'Airplane'

''

'plane'

0

2

'Boeing'

''

'747'

0

2

'Boeing'

''

'757'

 

生成记录组的方式又分为两种。

1、  从查询生成记录组

描述:利用树的查询语句(connect by…prior…start with…)生成记录组,设置树的属性来生成。

优点:编程简单,方便。

缺点:只适用于可以构造出树状查询语句的情况下。

例子:

   v_ignore       number;

   rg_emps        recordgroup;

begin

        rg_emps := find_group('EMPS');

     --如果非空,则清空数据

        if not id_null(rg_emps) then

               delete_group(rg_emps);

        end if;

        --构造记录组

        rg_emps := create_group_from_query('EMPS',

             'select 1, level, ename, NULL, to_char(empno) ' ||

             'from emp '                              ||

             'connect by prior empno = mgr '              ||

             'start with job = ''PRESIDENT''');

    v_ignore := populate_group(rg_emps);

    ftree.set_tree_property('tree_view.tree_emp', ftree.record_group, rg_emps);

end;

2、  用行列数据直接构造记录组

描述:记录组一般为行列结构,以循环方式直接向记录组中添加单元数据。

优点:可直接控制记录组的样式。

缺点:对多层结构,编程也较为复杂。

例子:

--单位CURSOR

   cursor cursor_dept is

      select   dname, deptno from dept order by dname;

   --雇员CURSOR

   cursor cursor_emp(p_dno number) is

      select   ename, empno from emp where deptno = p_dno order by ename;

   v_i            number;

   v_ignore       number;

 

   rg_emps        recordgroup;

   rg_depts       recordgroup;

 

   v_init_state   groupcolumn;

   v_level        groupcolumn;

   v_label        groupcolumn;

   v_icon         groupcolumn;

   v_value        groupcolumn;

begin

rg_depts := find_group('DEPTS');

--如有数据,则清空记录组

    if not id_null(rg_depts) then

          delete_group(rg_depts);

    end if;

   

    rg_depts := create_group('DEPTS');

    --这里自定义你需要的记录组中列的数据类型和长度

    --初始状态(指展开、收缩还是叶节点)

    v_init_state := add_group_column(rg_depts, 'init_state', number_column);

    --所在层数

    v_level      := add_group_column(rg_depts, 'level', number_column);

    --显示文本

    v_label      := add_group_column(rg_depts, 'label', char_column, 40);

    --图标

    v_icon       := add_group_column(rg_depts, 'icon', char_column, 20);

    --值

    v_value      := add_group_column(rg_depts, 'value', char_column, 5);

  

    v_i := 1;

    for deptrec in cursor_dept loop

         add_group_row(rg_depts, v_i);

       set_group_number_cell(v_init_state, v_i, 1);

       set_group_number_cell(v_level     , v_i, 1);

       set_group_char_cell  (v_label     , v_i, deptrec.dname);

       set_group_char_cell  (v_icon      , v_i, NULL);

       set_group_char_cell  (v_value     , v_i, to_char(deptrec.deptno));

       v_i := v_i + 1;

 

       for emprec in cursor_emp(deptrec.deptno) loop

            add_group_row(rg_depts, v_i);

            set_group_number_cell(v_init_state, v_i, 1);

          set_group_number_cell(v_level     , v_i, 2);

          set_group_char_cell  (v_label     , v_i, emprec.ename);

          set_group_char_cell  (v_icon      , v_i, NULL);

          set_group_char_cell  (v_value     , v_i, to_char(emprec.empno));

        v_i := v_i + 1;

       end loop;

    end loop;

    ftree.set_tree_property('tree_view.tree_org', ftree.record_group, rg_depts);

end;

结论:进行数据库设计时尽量把父子结构放在一张表,这样,使用查询生成记录组再生成树的方式最简单实用。如果不能实现,那么直接构造记录组也可生成树。如无特殊要求,一般不采取对树直接操作的方式。

附注:作者一般将生成树的程序放在Form Builder的“程序单元”中,在需要的地方调用来实时刷新树。

参考:Developer 6.0自带的PL/SQL程序库:navigate.pll
三、遗留问题
由于developer简化了树的设计,那么一些对树的转移、拷贝等操作就不太容易实现。这个课题还需要继续研究。

时间: 2024-11-01 03:47:46

Oracle Form Builder中使用树的心得的相关文章

Oracle Form中COMMIT的概述及使用技巧_oracle

1. COMMIT_FORM和COMMIT 都对form和数据库进行提交.针对form上面的数据变动提交到后台数据库,同时数据库提交数据. 2. DO_KEY('COMMIT_FORM') 它会首先执行KEY-COMMIT触发器里面的代码,如果没有这个触发器,则会做COMMIT_FORM一样的操作. 3. FORMS_DLL('COMMIT') 只针对代码中insert.update.delete语句进行提交,form上面的数据不提交. DG 里面提到: Replace COMMIT with

C++ Builder中如何保持控件的位置及大小

C++ Builder/Delphi是Inprise(原Borland)公司广受欢迎的可视化C++/Pascal开发工具,利用它可极大地加快应用程序的开发速度.但是,也正因为其是可视化编程工具,将控件拖放到Form后,控件的位置就固定死了.随着Form的大小或屏幕分辨率的改变,控件和Form本身的位置往往变得非常混乱.本文将介绍一些正确定位控件及Form的方法. 利用OnResize事件改变控件位置及大小 C++ Builder/Delphi中的Form控件有一个OnResize事件,Form的

C++ Builder中保持控件的位置及大小

C++ Builder/Delphi是Inprise(原Borland)公司广受欢迎的可视化C++/Pascal开发工具,利用它可极大地加快应用程序的开发速度.但是,也正因为其是可视化编程工具,将控件拖放到Form后,控件的位置就固定死了.随着Form的大小或屏幕分辨率的改变,控件和Form本身的位置往往变得非常混乱.本文将介绍一些正确定位控件及Form的方法. 利用OnResize事件改变控件位置及大小 C++ Builder/Delphi中的Form控件有一个OnResize事件,Form的

C++Builder中实现控件数组的功能

Borland C++ Builder作为Inprise(原Borland)公司新推出的快速应用程序开发工具(RAD),具有威力强大的C++语言和快捷便利的可视化编程完美结合的优点,遗憾的是其没有直接提供像VB中的控件数组的功能,需要开发者自己编程实现. VB中的一个控件数组可以 允许多个控件共享同一个事件句柄 提供了运行期间增加一个控件的机制 提供了一种方便的组合控件的方法. 前两项在C++ Builder中早已实现,而且CB更有一个优点.即不同类型的控件可以使用相同的句柄(只需在相关控件的O

OWB 11g循序渐进系列(0) Oracle Warehouse Builder 11g体系结构和组件

本文从 Oracle Documentation 整理得到 Warehouse Builder 11g 体系结构和组件 Oracle Warehouse Builder 是一个信息集成工具,可以利用 Oracle 数据库 将数据转换为高质量信息.Oracle 数据库是 Warehouse Builder 体系结构的中 央组件,因为它托管 Warehouse Builder 信息库和 Warehouse Builder 生成的 代码. 下图演示了 Warehouse Builder 软件主要组件的

Oracle的语句中的提示

 这所提到的提示,都是Oracle9i的提示.一个语句中,可以含有一个或多个提示,当含有多个提示时,某些或者全部提示会失效.        提示中表名可以是别名.为了更好的理解这些提示,先建立以下一些表.为了更加容易理解,会对一些常用提示给出例子,并给出对比,加深对提示的理解.create table t_huang (f1_num number(10)  not  null,f2_char varchar2(20)  not  null,f3_numnull number(10) null,f

【OH】Glossary Oracle词汇表(中)

Glossary [OH]Glossary Oracle词汇表(中) Oracle? Database Net Services Administrator's Guide 11g Release 2 (11.2) E41945-02 Glossary ● access control list (ACL) The group of access directives that you define. The directives grant levels of access to specif

spring mvc-springmvc的form:form标签中不能用JSP表达式?

问题描述 springmvc的form:form标签中不能用JSP表达式? 我这么写(一个普通的form标签)可以解析 form action="<%=request.getContextPath() %>/index.html"> 这么写就不对, form:form action="<%=request.getContextPath() %>/student/studentModifyFinished.act"> 解决方案 Sp

在C++Builder中使用Delphi文件

在使用多种语言和工具编写一个应用程序时,最为困难的事情之一是创建和维护定义文件的接口.幸运的是,C++Builder把这一切都替你做好了.当在项目中加入一个.PAS文件时,C++Builder会自动创建一个.HPP文件. 在CPP文件中,可以调用Pascal的函数.对象等.这为Delphi的程序员移植全部或部分的项目提供了便捷的途径. 下面是在C++Builder中使用Delphi代码的原则: 1.在C++Builder的窗体编辑器中,不能修改或编辑Delphi的窗体.但是可以修改Delphi窗