基于Java的报表系统

摘  要

现在是信息社会,各种信息都需要处理并直观展现,如股票,物价等信息都需要通过数据报表来展现、分析,因此高质量报表软件系统具有重要的实际意义。

   本论文课题研究探索了报表系统的开发方法与技术,综合应用Eclipse、 JAVA JDBCSWT/Jface、 RCP、XML、 CSS、DOM4J,IText,POI等先进技术,开发了基于WEB环境运行的报表设计器,实现了报表设计、模板生成、报表编辑,报表发布等基本功能,为进一步开发实用的报表系统奠定了基础。

关键词:报表,SWT/JfaceEclipseXML,B/S,RCP

Abstract

Now is the information society, all kinds of information need to be addressed and visual display, such as stock ,prices and other information needed to demonstrate through data reports, analysis, the statements of high-quality software system has important practical significance.

This paper statements subject to study and explore the system development methods and technology, comprehensive application of Eclipse, JAVA, JDBC, SWT / Jface, RCP, XML, CSS, DOM4J, IText, POI, and other advanced technology, the development of the operating environment based on the statements WEB design , Achieved a report design, template generation, editing statements, issued statements of such basic functions, for the further development of practical system laid the foundation for statements.

KEY WORDS: Report,SWT/JFaceEclipseXMLB/SRCP    

目 录

第一章 概述

1.1 课题背景与意义

1.2 报表系统发展概况

第二章 开发技术及环境

2.1软件环境

2.2 主要开发技术

第三章 系统设计

3.1系统体系结构

3.2 软件模块结构

3.3数据源与系统文件结构

3.3.1 系统数据源

3.3.2 系统文件结构

3.3.3 报表显示部分文件

第四章 系统实现

4.1主要实现算法

4.1.1新建报表流程图

4.1.2  新建数据源流程图

4.1.3编辑单元格流程图

4.1.4 保存报表流程图

4.1.5 生成电子表格流程图

4.1.6  发布报表流程图

4.1.7 编辑CSS流程图

4.1.8  生成模板流程图

4.1.9  配置服务器流程图

4.2 系统编码实现

4.2.1 系统的主界面实现

4.2.2 新建数据源

4.2.3  新建报表

4.2.4 编辑单元格

4.2.5  生成电子表格

4.2.6  发布报表

4.2.7 编辑CSS

4.2.8 生成模板

4.2.9 报表保存

4.2.10  配置服务器

第五章 系统典型界面

5.1系统主界面

5.1.1 编辑视图界面

5.1.2  属性视图界面

5.1.3  服务器视图界面

5.1.4  数据源视图界面

5.2部分功能界面

5.2.1 新建报表界面

5.2.2 新建数据源界面

5.2.3 设置CSS界面

5.2.4 设置服务器参数界面

5.2.5 设置报表参数界面

5.2.6生成模板界面

第六章 课题总结

致谢

参考文献

附录

第一章 概述

1.1 课题背景与意义

现在是信息社会,各种信息都需要处理并直观展现,如股票,物价等信息都需要通过数据报表来展现、分析,因此对高质量报表软件系统的需求非常强烈。

报表设计工具是报表系统的重要组成部分,使用报表设计工具,可对企业以及其他用户需要的各种报表进行设计,并在报表引擎上运行。报表设计工具功能包括数据源关联与访问、报表绘制、布局绘制、属性编辑、脚本编辑、图表编辑、表达式编辑、报表数据映射、报表预览调试等。可通过XML转换技术将报表转换换为PDF、Excel等格式输出。

随着B/S应用逐步取代C/S,市场上对Web环境下运行报表的要求日益强烈,C/S时期的报表工具纷纷进行了若干改进与加强,支持B/S结构。这些工具大都是对开源软件进行包装改造,基本上有两种流派:一类来自于FastReport这种基于Delphi的软件,通过控件方式实现Web报表,进而将报表计算移至服务器上进行,再改进为支持Linux;另一类自于Jasper的基于Java的开源软件。这些工具的整体思路还是沿袭了C/S时的方式,仍然是传统的分组报表的模式,仍然无法解决表样和大作量的代码编写问题,而且使用复杂,不能很好的发挥其效率,不能利用已有的软件功能,同时他们都是利用SWING/AWT来开发的,界面难看。  

因此,开发一个具有B/S结构、能适应中国国情、开源的、使用方便、界面美观的报表设计器是一个很多用户直期待的。但是,目前流行的报表软件产品中,比较适合中国情况的产品还是不多。

因此,进行本课题研究,开发报表设计器软件,对于开发适合中国特点的实用报表系统,促进企业与社会信息化,具有很好的实际意义。

1.2 报表系统发展概况

信息化的初期阶段,计算机作为一种新的生产工具,其主要功能是文字输出,如文件打印、表格输出等,相比较手工方式而言,工作效率大大提高。这个时期,用于报表生成的软件主要是WPS表格、CCED、Excel等文字处理工具,这些工具仅仅是将手工绘制报表的方式改为电子处理方式,未涉及到报表数据的集中、共享等处理。更确切地说,这个时期还没有真正意义上的报表工具。

     随着信息化程度的不断提高,C/S应用方式逐渐成熟,出现了很多报表工具软件,最著名的当属水晶报表和PB的DataWindow。水晶报表在上世纪一直被微软OEM,成为VB的内置报表工具,在微软的强大支持下,VB庞大的用户群为水晶报表培养了众多应用人员并积累了大量成功案例,从而产生了世界第一(用户量)的报表工具。DataWindow 是 PB 中获取专利技术的控件,它对数据的处理方法相当简洁,能处理各种显示格式,快速的报表制作能力深受PB开发者的喜爱。

      这些软件的基本特征是单数据源、条带式(BAND)分组统计模型,通过控件拖拽方式绘制报表,在不编码的情况下能完成简单地行式(分组)报表和单片交叉报表,数据集中在数据库中,可以共享。

     但这一时期的用户需求已经与前一阶段的需求大为不同用户希望放在数据库中的数据能以自己熟悉的方式展现(复杂的表样、统计运算等),而这些报表软件的数据模型源于国外的报表习惯,解决复杂表样的方法并不好,复杂的统计运算也要求开发人员编写大量的程序代码,导致报表开发时间太长,后期的维护工作量也很大。

随着B/S应用逐步取代C/S,市场上对Web报表的要求越来越强烈,C/S时期的报表工具纷纷进行了若干改进与加强,普遍支持B/S结构,新的报表软件也如雨后春笋一样不断出现。

   在报表工具的发展过程中,还有一类特殊的表格式产品,最著名有ormula1和华表。这种类Excel 的工具,展现能力非常强,但是因为没有数据模型,导致其数据处理能力几乎为零,程序员需要按格编写代码往里填数。相比较分组式报表工具,类Excel工具能彻底解决复杂报表的样式问题,所以在实际应用中它一直是与分组报表互补的一类产品。

SWT/JFACE是Eclipse推出优秀的JAVA图形API。

RCP,也就是富客户端,是在Eclipse3.0之后分离出来的一个平台。RCP技术其实就是插件开发,可以在一个很小的模板上加入各种插件,扩展性能。现在RCP已经成为Eclipse开源项目的一个亮点,在国际上广泛的使用大量PCR来开发桌面应用程序。在RCP平台上,可以使用Eclipse的插件机制来快速开发独立应用的桌面应用,从而轻松拥有Eclipse的界面结构和界面元素,节省了很多开发精力。

运用SWT/Jface和RCP技术来开发报表,是当前报表开发的主流方向。一方面,SWT/Jface可以提供优秀的图形界面,克服JAVA桌面应用界面难看的缺陷一方面RCP技术可以提高开发效率。联合运用SWT/Jface和RCP技术,可以开发出优秀的报表产品。

第二章 开发技术及环境

2.1软件环境

本系统的开发环境

操作系统:   Window server 2003标准版

应用服务器:  Tomcat5.5

开发平台:eclipse3.3 ;jdk1.5

2.2 主要开发技术

SWT/Jface

SWT(Standard Widget Toolkit )是标准控件工具集。Jface意为JAVA face。由于SUN的AWT/SWING技术在与本地界面融合方面存在缺陷,因此IBM开发了SWT,使得界面风格和本地保持一致。而Jface是SWTa的扩展包,采用MVC的设计模式,使用更加方面。

RCP

RCP(Rich Client Platform)意为富客户平台。在RCP平台上,可使用Eclipse的插件机制来快速开发独立应用的桌面应用,从而轻松拥有Eclipse的界面结构和界面元素,节省了很多开发精力。

Dom4j 

Dom4j (Document Object Model for JAVA)是一个易用的、开源的库,用于XML,XPath和XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP。Dom4j使用起来非常简单,效率高。只要了解基本的XML-DOM模型就能使用。

POI

POI(Point of Interest)意为为兴趣点,JAVA与MS Office交互时用到的第三方JAR,也是开源的,属于Apache的一个项目,用法简单。主要用来读写OLE 2复合文档结构,本系统主要用来操作EXCEL。

IText

iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。用法很简单,效率很高。

Lomboz

lomboz是用来开发j2ee应用、免费eclipse插件,用它可以大大加快web开发、部署等工作。

第三章 系统设计

3.1系统体系结构

本系统采用三层B/S架构 ,分别为表示层、设计层和数据层如图3-1所示。

  1. 表示层(Presentation-Tier)

  是报表显示层。本报表系统的表示层有三种类型:Web类型,Excel类型,Pdf类型。

(2)设计层(Designer-Tier)

 是本报表系统的重中之重。设计层设计的好坏直接影响到报表的使用。其主要任务是建立报表、修改报表、发布报表、生成模板等。这涉及到报表的数据来源,报表的格式,报表输出,是连接表示层和数据层的桥梁。

(3)数据层(Data-Tier)

主要是和用户有关。本报表系统可以与几种常用的数据库系统交互。报表中可以输入的数据很多,如图表、序列号、常量等。数据层可以存储并管理这些数据。

           图3-1系统体系结构

3.2 软件模块结构

本系统的软件模块结构,如图3-2所示。

                      图3-2 系统软件模块结构图

图3-2中各模块的基本功能如下:

   新建报表:设置报表的名字、每页显示数目、选用报表模板;把这些数据存到Preferences中,供保存报表使用。

   新建数据源:设置数据源名称,用它来标识数据连接;选择数据库类型,并设置各种连接参数;进行数据源说明;进行连接测试;连接成功后把数据源名称和各种连接参数保存到dataSource.xml文件中,供以后使用;而数据源说明就生成一个文本文件保存。

   编辑单元格:设置单元格的数据,数据源列、函数、系列号、图像;设置颜色,字体;设置所对的行列是否扩展所对应的行列是否排序。这些都要用一定的格式保存起来,供报表显示时使用。

   保存报表:设置单元格属性后,保存设置内容。先从Preferences读取报表相关数据,然后生成报表的xml;遍历表格,把表格各种信息填到xml中。

编辑报表:保存表格后,如觉得不满意,可以打开报表修改。读取xml,把相关信息填到相应的单元格。也可以设置报表的每页的行数、报表发布者、发布时间、报表说明。

生成电子表格:电子表格可用来直接发布,也可用来编辑。先读取报表xml文件,得到各个单元格的数据源,根据数据源不同,得到不同的数据,并填到相应的电子表格内。可以设置电子表格的属性。

发布报表:先设置发布目录,然后把项目文件夹下Files目录下的名和Preferences中保存相同的,后缀名为xml、xls、css、pdf的文件都复制到发布目录下。如发布目录已有相同文件,就覆盖。

编辑CSS:CSS决定网页页面显示格式,对报表非常重要。本系统提供一个模板,旁边还有介绍各种标记的代表的内容的提示,这样用户就可以自己修改。修改完后点“确定”,生成报表名+“.css”的样式文件。

生成模板:CSS不是很难,但要做一个好看的格式却很难,所心有必要把前面生成的CSS文件保存起来,提供下次使用。首先设置模板名字,然后设置说明,点“确定”后,系统会把当前报表的CSS文件复制到模板xml文件,并生成说明的txt文件。

配置服务器:配置发布目录、端口、最大线程数,以方便使用。

3.3数据源与系统文件结构

3.3.1 系统数据源

报表就是数据的显示,所以数据源很重要。本系统的数据源方案如下:

  1. 提供建立数据源及管理数据源的功能。针对不同类型的数据库数据,建立相应的数据源。建立了数据源后,就用一个XML文件保存数据源信息,以后可直接从XML文件读取或修改连接信息。
  2. 提供对其它类型数据源的支持。主要支持EXCEL文件、函数、系列号、公式等数据源。EXCEL文件可以直接解析为WEB格式,而函数,系列号,公式,图像等可以直接插入。

    3.3.2 系统文件结构

本系统作为一个桌面应用系统,涉及到许多文件系统,不管用户还是开发者,都有可能容易迷失在文件堆中,所以必须科学管理。为了解决此问题,本系统设计了系统主目录文件结构,以下是系统主目录的的文件截图

                    

                    图3-4 系统主目录文件结构图  

图3-4中各文件的功能如下:

.metadata文件夹:系统自动生成,保存有日志文件。

.setting文件夹: 系统自动生成,用于保存项目的各个参数。

Bin文件夹:存放已经编译过的JAVA的.class文件。

DataSource文件夹:存放数据源的dataSource.xml文件,其中还有各种.txt文件,用来说明各个数据源。该文件夹结构如图3-5所示:

                    图3-5 DataSource文件夹示意图

Files文件夹用来存放所生成的报表。其中有存放报表信息的xml文件,也有生成为电子表格的.xls文件、pdf文件。当然也存放了报表说明的.txt文件,其结构如图3-6所示:

图3-6 Files文件夹示意图

       图3-6   Files文件夹结构示意图

icons文件夹:用来存放图象,如按钮图标。

intro文件夹:系统自动生成。

lib文件夹:用来存放第三方JAR包。

META-INF文件夹:系统自动生成,里面有MENIFEST.MF,在这个文件里有描述插件各种信息基本信息。

src文件夹:是源文件,其结构如下图所示:

                

图3-7 src文件夹示意图

从图中可知,src文件夹包括两个包,一个是xautreportdesign包,里面有Activator.java文件,这是RCP的激活类。另一个是com包。其实这个包里有三个子包:com. Xautreportdesign.action,主要用来存放菜单,工具栏动作类的;com. Xautreportdesign.util,主要用来存放一些工具类的,这些工具类对全局都有用;com.Xautreportdesign.win,主要是界面方面的类,有一些是自动生成后我修改的。

com. Xautreportdesign.action包中的一部分类如图3-8所示:

             图3-8 com. Xautreportdesign.action包中文件示意图

com. Xautreportdesign.util包中的类如图3-9所示:

                图3-9 com. Xautreportdesign.util包中文件示意图

com. Xautreportdesign.win包中类类如图3-10所示:

             图3-10 com. Xautreportdesign.win包中文件示意图

Template文件夹:是保存模板的文件夹,里面有模板文件.css文件,也有模板说明.txt文件,如图3-11所示:

               

 图3-11 Template文件夹示意图

.classpath、.project、build.propertiesjavaCompiler...argsplugin.xmlplugin_customization.ini都是系统自动生成的。

build.xml:是用ant生成的,为系统打包用。

Report.product:是要生成的新产品配置文件。

splash.bmp:系统启动时产闪动画面使用。

3.3.3 报表显示部分文件

对于报表WEB显示部分,有如下重要文件或文件夹:

dataSource文件夹存放数据源文件dataSourece.xml

photo文件夹:存放需要的图片文件。

.css文件:是报表的css文件。

report.jsp:是解析保存报表信息的.xml的文件。

exceltoweb.jsp:是解析EXCEL并生成WEB的文件。

第四章 系统实现

4.1主要实现算法

4.1.1新建报表流程图

                 图4-1  新建报表算法流程图

     该算法首先判断是否已有同名的报表,然后判断行数是否为数字,最后存入Preferences中。

4.1.2  新建数据源流程图

                 图4-2  新建数据源算法流程图

   该算法先选择合适自己的数据库,然后输入信息,最后连接,看是否成功,若成功就把信息保存起来。

4.1.3编辑单元格流程图

图4-3  新建报表算法流程图

   该算法首先要得到当前鼠标的位置,然后转化为表格的行列,最后选择数据源,并设置单元格属性。

4.1.4 保存报表流程图 

             图4-4  保存报表算法流程图

该算法首先从Preferences中读取报表相关信息,生成报表名的xml文件。然后遍历表格,读取各非空单元格的值及属性,填入写入小xml文件中,最后看是否用到模板,如用到,就生成报表名的css文件。生成xml的代码如下所示:

<XautReportFile Name="zainan" tempname="Template" rownum="8" ownerName="杨济忠" time="2008年6月3日" intro="true">

 <Columns>

   <Column DataSource="D:zainanDS.ID" Span="纵扩展" Arrange="不排序" Color="RGB {255, 255, 255}" Font="Tahoma.8.0">A1</Column>  

XautReportFile中 “Name”代表报表的名字,“tempname”代表报表用到的模板,“rownum”代表WEB页每页显示的行数,“ownerName”代表作者,time代表发布时间,intro代表是否有说明内容。

而Columm代表一个单元格,“DataSource”代表数据源,里面不同的部分又代表不同的意思:

如前面为“D:”,那代表数据库,中间代表前面建的数据源的名称,最后代码数据源的列。

如前面是“I:”,那代表常量,后面部分就是常量的值。、

如前面是“S:”,那代表系列号,后面代表系列号的一部分。

如前面是“F:”,那代表的是函数,后面是函数。

“Span”,代表扩展情况。扩展就是其它单元格的值是否依赖这个单元格的值;“Arrange”代表是否排序;“Color”代表是颜色,;“Font”代表字体。而这个单元格的ID是A1。

4.1.5 生成电子表格流程图


              图4-5  生成电子表格算法流程图

   该算法首先从Preferences中得到当前报表名,然后读取报表XML文件,得到数据源名称。读取数据源XML,遍历得到数据源的各种参数。用这些参数连接数据库。用POI创建EXCEL文件。把数据库中数据写入EXCEL文件。

4.1.6  发布报表流程图

              图4-6  发布报表算法流程图

该算法首先从Preferences中查看发布目录,如有,就复制报表XML到发布目录,如没有,就设置。然后就开始判断是否有相关文件,如有,就一同复制,因为不复制,就没有用。

4.1.7 编辑CSS流程图

            图4-7  编辑CSS算法流程图

该算法首先从CSS模板中读出模板内容,并显示出来,提供用户修改。修改完成后点确定,从Preferences得当前报表,然后生成报表的CSS文件,如已有相同的就覆盖。最后把修改后的CSS写入报表文件。

4.1.8  生成模板流程图

                图4-8  生成模板算法流程图

   该算法首先设置要生成模板的模板名及说明。然后生成模板文件,当然是CSS类型。如模板说明不为空,也生成文件文件类型的说明书。然后从Preferences中得到当前报表,由此得到当前报表的CSS文件,最后把这CSS文件的内容写入模板文件里。

4.1.9  配置服务器流程图

               图4-9  配置服务器算法流程图

    该算法首先读取服务器配置文件并显示各个参数,这可以修改。点确定后,就把修改后值写入配置文件,并更新相关视图。

4.2 系统编码实现

4.2.1 系统的主界面实现

本系统采用Eclipse RCP技术,也就是开发可以独立运行的Eclipse的插件。运用RCP技术,可以实现与Eclipse一样友好的界面,可以方便地组装成一个很强大的系统,因为这是采用插件机制。本系统的主界面如图4-1所示:

            图4-1 报表设计系统主界面图

由图4-1可以看到本系统和Eclipse界面有很大的相似性。本系统主要用到了包com.xautreportdesign.win。其中各个类的功能及重要代码说明如下:

Application类:是RCP程序的入口类,RCP程序启动后第一个执行就是它,它负责程序的载入与退出。这个类是建立项目后自动生成的,平常情况不需要修改。

ApplicationWorkbenchAdvisor是配置工作台的类工作台的初始化就在这完成。这个类是建立项目后自动生成的,可以修改成自己需要的。这个类的部分代码如下:

ApplicationWorkbenchWindowAdvisor:用来设置窗口。一个工作台可以有多个窗口,所以可以多个该类的对象。这个类是建立项目后自动生成的,可以修改成自己需要的。下面代码说明了窗口大小为(700, 550),有工具栏,窗口标题,显示状态栏,生成系统托盘等。以下是该类的部分实现代码:

public void preWindowOpen() {

/** 设置窗口初始化的各种属性 */

IWorkbenchWindowConfigurer configurer = getWindowConfigurer();

configurer.setInitialSize(new Point(700, 550));

configurer.setShowCoolBar(true);

configurer.setShowStatusLine(false);

configurer.setTitle("报表生成系统");

configurer.setShowPerspectiveBar(true);

configurer.setShowStatusLine(true);

final IWorkbenchWindow window = getWindowConfigurer().getWindow();

/** 创建系统托盘 */

trayItem = initTrayItem(window);

/** 如果支持系统托盘,则创建托盘的菜单 */

if (trayItem != null) {

createPopupMenu(window);

}

}

    

Perspective类:是透视图类。透视图是各个视图,编辑面组成的一个专用的程序界面。本类是项目默认生成,当然也可以写自己的视图,只要实现IperspectiveFactory接口。下面就是本透视图的布局部分代码,效果如图4-1所示。

public void createInitialLayout (IPageLayout layout) {

String editorArea = layout.getEditorArea();

layout.setEditorAreaVisible(true);

layout.setFixed(false);

// layout.addView(View.ID,IPageLayout.LEFT, 0.25f, editorArea);

IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT,

0.25f, editorArea);

left.addPlaceholder(DatasourceView.ID);

left.addPlaceholder(ServerView.ID);

layout.getViewLayout(ServerView.ID).setCloseable(false);

layout.getViewLayout(ServerView.ID).setMoveable(false);

layout.addPlaceholder(editAreaView.ID, IPageLayout.TOP, 0.50f,

editorArea);

layout.addPlaceholder(AttributeView.ID, IPageLayout.BOTTOM, 0.25f,

editorArea);

layout.getViewLayout(AttributeView.ID).setCloseable(false);

layout.getViewLayout(AttributeView.ID).setMoveable(false);

}

ApplicationActionBarAdvisor类负责创建和配置工作台窗口上主菜单,工具栏,状态栏等,是报表各种功能模块相关入口。下面的代码是用来建立系统托盘项。其中new Separator()是画一条分隔线,在菜单工具栏中也用到。

public void fillTrayItem(MenuManager trayMenu) {

trayMenu.add(deployAction);

trayMenu.add(new Separator());

trayMenu.add(exampleAction);

trayMenu.add(aboutAction);

editAreaView类:是编辑视图类。视图相当于一个小窗口,显示某一方面的内容,可以在一个页面上放置几个视图。视图可通过两种方式创建:

一.通过扩展点:修改plugin.xml文件,设置视图扩展点,在最后一行的</plugin>前加入,下面的代码说明了扩展点是org.eclipse.ui.views,视图名字是“编辑区”,对应的JAVA文件是com.xautreportdesign.win.editAreaView,ID是视图的标识,为XautReportDesign.EditAreaView。对于其它视图,都可以这样创建:

<extension

         point="org.eclipse.ui.views">

      <view

            name="编辑区"

            class="com.xautreportdesign.win.editAreaView"

            id="XautReportDesign.EditAreaView">

      </view>

   </extension>   

二.通过继承抽象类ViewPart类,要改写类中createPartControl,setFocus方法。

本视图实现部分的代码如下所示:

public void createPartControl(Composite parent) {

createToolbar();

if (!isedit) {

setPartName("编辑" + reportName);

} else

setPartName("(未保存)编辑" + reportName);

createTable(parent, colnum, rownum);

  }

上面的代码是实现视图内容,其中最重要的是createTable()方法这个方法是在视图中创建类似EXCEL中的表格。下面的代码创建一个表格,并设置表格的样式,部分代码如下:

Composite c1 = new Composite(parent, SWT.NONE);

c1.setLayout(new FillLayout());

table = new Table(c1, SWT.SINGLE | SWT.HIDE_SELECTION

| SWT.FULL_SELECTION);

table.setHeaderVisible(true);

table.setLinesVisible(true);

table.setRedraw(true);

  对于表格的列号,下面的代码创建列名从A开始的20个列,其中得把数字转化为字符型 ,其实现代码如下:

  for (int i = 0; i < 20; i++) {

TableColumn column = new TableColumn(table, SWT.CENTER);

column.setText("  " + String.valueOf((char) (65 + i)) + "  ");

column.pack();

}

而对于行号,下面的方法按钮附加到每一行的第一列,在按钮上写数字。这样做的原因是使表格可编辑。实现方法如下:

Button b[] = new Button[30];

for (int i = 0; i < 30; i++) {

final TableItem item = new TableItem(table, SWT.NONE);

item.setText(i + 1, " ");

editor[i] = new TableEditor(table);

b[i] = new Button(table, SWT.PUSH);

b[i].setText(" " + (i + 1) + " ");

editor[i].grabHorizontal = true;

editor[i].minimumHeight = b[i].getSize().y;

editor[i].minimumWidth = b[i].getSize().x;

editor[i].setEditor(b[i], item, 0);

} 

   编辑是在属性视图完成的,所以需完成数据绑定。下面代码的作用是数据绑定,它获取鼠标所在单元格:

table.addMouseListener(new MouseAdapter() {

public void mouseDown(MouseEvent event) {

Control old = editor1.getEditor();

if (old != null)

old.dispose();

Point pt = new Point(event.x, event.y);

final TableItem item = table.getItem(pt);

if (item != null) {

int column = -1;

for (int i = 0; i <= 20; i++) {

Rectangle rect = item.getBounds(i);

if (rect.contains(pt)) {

column = i;

break;

}

}

  要把表格内容填到属性视图中相应的组件上,实现的方法是首先得到属性视图,其中通过getter()方法得到视图组件,这样就可以修改组件的值,同时得到表格单元格的值,用字符串分析技术得到不同的值,并填充到属性视图table中。实现代码如下:

final int col = column;

// 数据绑定

IViewPart vp = getViewSite().getPage().findView(

AttributeView.ID);

AttributeView av = (AttributeView) vp;

Label titleLabel = av.getLabel1();

String colId = String

.valueOf(table.getSelectionIndex() + 1);

titleLabel.setText("单元格:"

+ String.valueOf((char) (64 + column)) + colId);

Combo combo = av.getCombo();

Combo combo11 = av.getCombo11();

Combo combo1 = av.getCombo1();

Combo combo2 = av.getCombo2();

String columnValue = item.getText(column);

int i = columnValue.indexOf("@", 1);

if (i == -1) {

combo.select(0);

combo11.select(0);

combo1.select(0);

combo2.select(0);

} else {

String datasource = columnValue.substring(0, i);

if (datasource.startsWith("F:")) {

combo.select(2);

combo11.setText(datasource.substring(2));

} else if (datasource.startsWith("S:")) {

combo.select(1);

combo11.setText(datasource.substring(2));

} else if (datasource.startsWith("D:")) {

int n = datasource.indexOf(".");

combo.setText(datasource.substring(2, n));

combo11.setText(datasource.substring(n + 1));

} else if (datasource.startsWith("I:")) {

combo.select(0);

combo11.setText(datasource.substring(2));

} else {

combo.select(0);

combo11.setText(datasource);

}

  

AttributeView类:属性视图类,也就是用来修改单元格的属性。

本视图的重点工作是编辑单元格属性,所以工作重点是和编辑视图交互,部分代码如下:

public void fillInTable(final Composite parent)

throws NumberFormatException {

IViewPart vp = getViewSite().getPage().findView(editAreaView.ID);

editAreaView eav = (editAreaView) vp;

Table table = eav.getTable();

int i = label1.getText().indexOf(":");

String tableLocal = label1.getText().substring(i + 1);

String colid = tableLocal.substring(0, 1);

String rowid = tableLocal.substring(1);

char[] char1 = colid. toCharArray ();

int k = char1[0] - 64;

TableItem item = table.getItem(Integer.parseInt(rowid) - 1);

String valueString = "";

       if (combo. getSelectionIndex() == 0) {

valueString = "I:" + combo11.getText() + "@" + combo1.getText()

+ "@" + combo2.getText();

} else if (combo. getSelectionIndex() == 1) {

valueString = "S:" + combo11.getText() + "@" + combo1.getText()

+ "@" + combo2.getText();

} else if (combo.getSelectionIndex () == 2) {

valueString = "F:" + combo11.getText() + "@" + combo1.getText()

+ "@" + combo2.getText();

} else {

valueString = "D:" + combo.getText() + "." + combo11.getText()

+ "@" + combo1.getText() + "@" + combo2.getText();

}

item.setText(k, valueString);

MessageDialog.openInformation(parent.getShell(), "修改成功", "修改成功!");

}

 上述代码中,首先得到编辑视图,然后得到视图表格,最后定位到具体单元格。然后把各个控件的值按一定的格式写入单元格。然后提示修改成功。

DatasourceView类:显示已有的数据源及数据源的列。主要是读取Datasource文件夹下dataSourece.xml文件中的内容,并把它们用树形表示出来。

ServerView类:是服务器视图,显示已发布到服务器上的报表文件,包括xml,excel,pdf文件。这是用TreeViewer来实现的,这个类采用MVC设计模式,必须实现setContentProvidersetLabelProvider方法。实现代码如下:

tree.setContentProvider(new ITreeContentProvider() {

private String path;

public Object[] getChildren(Object element) {

return ((File) element).listFiles();

}

public Object[] getElements(Object element) {

Preferences preferences = new ConfigurationScope()

.getNode("com.XautReportDesign.product");

try {

//得到报表文件夹目录

path = FileLocator.toFileURL(

Platform.getBundle("XautReportDesign") .getEntry("")).getPath().toString()

+ "Files/";

} catch (IOException e) {

e.printStackTrace();

}

//如果发布目录不存在,就用报表文件夹目录

String deployDirectry = preferences.get("deployDirectry", path

.substring(1));

File cFile = new File(deployDirectry);

File[] roots = cFile.listFiles();

List<File> rootFolders = new ArrayList<File>();

for (int i = 0; i < roots.length; i++) {

if (roots[i].isFile()

&& (roots[i].getAbsolutePath().endsWith("xml")

|| roots[i].getAbsolutePath().endsWith(

"pdf") || roots[i]

.getAbsolutePath().endsWith("xls")))

rootFolders.add(roots[i]);

}

return rootFolders.toArray();

}

public boolean hasChildren(Object element) {

Object[] obj = getChildren(element);

return obj == null ? false : obj.length > 0;

}

public Object getParent(Object element) {

return ((File) element).getParentFile();

}

public void dispose() {

}

public void inputChanged(Viewer viewer, Object oldInput,

Object newInput) {

}

});

 上面代码用到了Preferences,它是一种持久化API,其目的是存储少量数据提供一个高效的存储设备。Preferences采用树形结构,用Key/Value格式。本系统中用它来存储正在编辑报表名称,报表发布目录等。

String deployDirectry = preferences.get("deployDirectry", path

.substring(1));

上面的代码说明,如果没有前面的值,deployDirectry就用等于后面的值。

得到文件目录后,就用遍历找出后缀名为xml、xls、pdf的文件,并显示。

4.2.2 新建数据源

    报表要与各种数据打交道。新建数据源的对话框如图4-3所示。 新建数据源用到的菜单类为newDataSourceAction,newDataSourceDialog类。NewDataSourceAction继承Action类,并实现IworkbenchAction,所以得实现run方法。事实上,本系统的动作类都和newDataSourceAction类似。本类运行时,先打开一个对话框,然后关闭数据源视图、属性视图,再显示这两个视图,这样就起到刷新目的,其实现代码如下:

public void run() {

if (workbenchWindow == null) {

return;

}

newDataSourceDialog dialog = new newDataSourceDialog(Display

.getCurrent().getActiveShell());

dialog.open();

IWorkbenchPage page = workbenchWindow.getActivePage();

dataSourceView=workbenchWindow.getActivePage().findView(DatasourceView.ID);

if(dataSourceView!=null){

page.hideView(dataSourceView);

} attributeView=workbenchWindow.getActivePage().findView(AttributeView.ID);

if(attributeView!=null){

page.hideView(attributeView);

}

if (page != null)

try {

page.showView(AttributeView.ID);

page.showView(DatasourceView.ID);

} catch (PartInitException e) {

ErrorDialog.openError(workbenchWindow.getShell(), "打开视图错误", e.getMessage(), e.getStatus());

}

}

     下面的代码实现试连接的功能,根据不同的数据库,提供不同的连接字符串:

button.addMouseListener(new MouseListener() {

public void mouseDown(MouseEvent e) {

driverClass = makeClassDriver();

if (DataConn.getINSTANCE().isExit(DataSourceName, riverClass,

dataURL.getText().trim(), userName.getText().trim(),

userpassword.getText().trim(),

sqlString.getText().trim())) {

MessageDialog.openInformation(Display.getCurrent()

.getActiveShell(), "连接数据库", "连接数据库成功");

}

}

public void mouseUp(MouseEvent e) {

// TODO Auto-generated method stub

}

public void mouseDoubleClick(MouseEvent e) {

// TODO Auto-generated method stub

}

});

    试连接用到com.xautreportdesign.util.DataConn,这是平常的数据库连接方式,此处不写代码了。

4.2.3  新建报表

在新建报表中,本系统只提供了设置报表的简单参数,为处理方便,先把这些放入Preferernces中,这样以后可以随时快速访问。

Preferences是一种持久化API,其目的是为存储少量数据提供一个高效的存储设备。Preferences采用树形结构,用Key/Value格式。本系统中用它来存储正在编辑报表名称,报表发布目录等。

String deployDirectry = preferences.get("deployDirectry", path

.substring(1));

上面说明,如果前面的值为NULL,就用后面参数的值。

在新建报表中,报表信息放在Preferences中,在保存时就可以访问,得到当前编辑的报表。代码如下:

Preferences preferences = new ConfigurationScope()

.getNode("com.XautReportDesign.product");

preferences.put("name", fileName);

preferences.put("rownum", rownum);

if(Combo1.getText()!=null){  preferences.put("tempname",Combo1.getText().substring(0,Combo1.getText().lastIndexOf(".")));

}

try {

preferences.flush();

} catch (Exception e) {

e.printStackTrace();

}

4.2.4 编辑单元格

编辑单元格就是在属性视图中编辑单元格,怎样定位表格的单元格很重要。下面代码中先得到鼠标位置,然后找出它在表格中的行列,并把行列化为“A1”这样的形式显示在属性视图的Label1中。在编辑视图中,用如下的代码实现两视图互动:

Point pt = new Point(event.x, event.y);

final TableItem item = table.getItem(pt);

if (item != null) {

int column = -1;

for (int i = 0; i <= 20; i++) {

Rectangle rect = item.getBounds(i);

if (rect.contains(pt)) {

column = i;

break;

}

}

final int col = column;

// 数据绑定

IViewPart vp = getViewSite().getPage().findView(

AttributeView.ID);

AttributeView av = (AttributeView) vp;

Label titleLabel = av.getLabel1();

String colId = String

.valueOf(table.getSelectionIndex() + 1);

titleLabel.setText("单元格:"

+ String.valueOf((char) (64 + column)) + colId);

在属性视图中,是这样根据Label1得到相应的单元格的,把大写字母化为一个数字,定位到单元格。代码如下:

IViewPart vp = getViewSite().getPage().findView(editAreaView.ID);

editAreaView eav = (editAreaView) vp;

Table table = eav.getTable();

int i = label1.getText().indexOf(":");

String tableLocal = label1.getText().substring(i + 1);

String colid = tableLocal.substring(0, 1);

String rowid = tableLocal.substring(1);

char[] char1 = colid.toCharArray();

int k = char1[0] - 64;

TableItem item = table.getItem(Integer.parseInt(rowid) - 1);

4.2.5  生成电子表格

这里要用到POI第三方JAR包。这个包可以生成、解析、直接编辑EXCEL文件。生成电子表格的代码如下:

          //前面已经连接了数据库,现在就是要把数据填到EXCEL文件中。

HSSFWorkbook we = new HSSFWorkbook();

HSSFSheet s = we.createSheet(reportName);

we.setSheetName(0, "first sheet");

HSSFRow row = s.createRow(0);// 创建一行

HSSFCell[] cell = new HSSFCell[colnum];

HSSFCellStyle cellStyle = we.createCellStyle();

// 对齐

cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);

for (short i = 0; i < colnum; i++) {

cell[i] = row.createCell(i);

// 将单元格定义成UTF_16编码,这样才能使输出数据不会乱码

cell[i].setEncoding(HSSFCell.ENCODING_UTF_16);

cell[i].setCellValue(header[i]);

cell[i].setCellStyle(cellStyle);

}

try {

rs.last();

int num = rs.getRow();

rs.first();

for (int i = 0; i < num && rs.next(); i++) {

HSSFRow datarow = s.createRow(i + 1);

HSSFCell data[] = new HSSFCell[colnum];

for (short k = 0; k < colnum; k++) {

String value1 = null;

if (DataSource[k].substring(0, 2).equals("D:")) {

// 根据数据库中的不同的类型调用不同的函数

switch (remeta.getColumnType(colSort[k])) {

case Types.CHAR:

value1 = rs.getString(colSort[k]);

break;

case Types.VARCHAR:

value1 = rs.getString(colSort[k]);

break;

case Types.BOOLEAN:

value1 = String.valueOf(rs .getBoolean(colSort[k]));

break;

case Types.DISTINCT:

value1 = String.

valueOf(rs.getLong(colSort[k]));

break;

case Types.TIME:

   value1 = String.valueOf(rs.getTime(colSort[k],

Calendar.getInstance()));

break;

case Types.INTEGER:

value1 = String.valueOf(rs.getInt(colSort[k]));

break;

case Types.DECIMAL:

value1 = String.valueOf(rs.getBigDecimal(colSort[k]));

break;

case Types.FLOAT:

value1 = String.valueOf(rs

.getFloat(colSort[k]));

break;

case Types.SMALLINT:

value1 = String.valueOf(rs

.getShort(colSort[k]));

break;

case Types.BIGINT:

value1 = String.valueOf(rs

.getLong(colSort[k]));

break;

case Types.DATE:

value1 = String.valueOf(rs.getDate(colSort[k]));

break;

case Types.OTHER:

value1 = rs.getObject(

colSort[k]).toString();

break;

}

}

if (DataSource[k].startsWith("I:")) {

value1 = DataSource[k].substring(2);

}

if (DataSource[k].startsWith("S:")) {

if (DataSource[k].substring(2, 3).equals("0")) {

value1 = String.valueOf(index);

index++;

}

if (DataSource[k].substring(2, 3).equals("A")) {

value1 = String

.valueOf((char) (64 + index));

index++;

}

if (DataSource[k].substring(2, 3).equals("a")) {

value1 = String

.valueOf((char) (97 + index));

index++;

}

}

try {

data[k] = datarow.createCell(k);

data[k].setCellValue(value1);

data[k].setCellStyle(cellStyle);

} catch (Exception e) {

e.printStackTrace();

}

}

}

try {

we.write(fos);

} catch (IOException e) {

e.printStackTrace();

}

} catch (SQLException e) {

e.printStackTrace();

}

try {

fos.close();

} catch (IOException e) {

e.printStackTrace();

}

在生成EXCEL文件过程中,要访问两个XML文件、连接一次数据库,这很费时间,所以有必要显示进度,不然用户可能认为没反应,把生成进度条做成一个函数,这样可以随时调用。这里用到了多线程,其中每个线程之间隔0.3秒,共有5个线程。其函数代码如下:

public void doJob(final String taskname) {

IProgressService progressService = PlatformUI.getWorkbench()

.getProgressService();

IRunnableWithProgress runnable = new IRunnableWithProgress() {

public void run(IProgressMonitor monitor)

throws InvocationTargetException, InterruptedException {

monitor.beginTask(taskname, 5);

for (int i = 0; i < 5; i++) {

try {

Thread.sleep(300);

monitor.setTaskName(taskname + i);

monitor.worked(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

monitor.done();

}

};

try {

progressService.runInUI(progressService, runnable, null);

} catch (Exception e) {

e.printStackTrace();

}

}

4.2.6  发布报表

   发布报表其实就是复制文件到另一个目录。怎样复制是一个比较关键的问题,因为有时得复制几个文件,而且文件操作很费时间。本系统设计了一个比较实用的函数来进行复制,代码如下:

   public void movefile(String deployDirectry, String SourcefileName,

String fileName, String fileType, String forderName) {

FileInputStream fIstream = null;

FileOutputStream fOstream = null;

try {

File fileInput = new File(Constant.getAPLICATIONDIR()

+ forderName + SourcefileName + fileType);

fIstream = new FileInputStream(fileInput);

} catch (IOException e) {

e.printStackTrace();

}

try {

File fileOut = new File(deployDirectry + "/" + fileName + fileType);

if (fileOut.exists()) {

fileOut.delete();

}

fOstream = new FileOutputStream(fileOut);

} catch (FileNotFoundException e) {

e.printStackTrace();

}

byte[] b = new byte[1];

try {

while (fIstream.read(b) != -1) {

fOstream.write(b);

}

} catch (IOException e) {

e.printStackTrace();

}

try {

fOstream.close();

fIstream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

可以看出,这不只对一种格式的文件,而是各种文件,以及不同的目录。如本系统这样调用这个函数:

movefile(deployDirectry, reportName, reportName, ".xml", "Files/");

if (tempName != null)

doJob("复制css文件");

movefile(deployDirectry, tempName, reportName, ".css", "Template/");

File pdfFile = new File(Constant.getAPLICATIONDIR() + "Files/"

+ reportName + ".pdf");

if (pdfFile.isFile()) {

doJob("复制pdf文件");

movefile(deployDirectry, reportName, reportName, ".pdf", "Files/");

}

File xlsFile = new File(Constant.getAPLICATIONDIR() + "Files/"

+ reportName + ".xls");

if (xlsFile.isFile()) {

doJob("复制Excel文件");

movefile(deployDirectry, reportName, reportName, ".xls", "Files/");

}

File txtFile = new File(Constant.getAPLICATIONDIR() + "Files/"

+ reportName + ".txt");

if (txtFile.isFile()) {

doJob("复制说明文件");

movefile(deployDirectry, reportName, reportName, ".txt", "Files/");

}

deployDirectry, reportName, reportName这三个变量在前面已经赋值了,可以很方便地处理复制问题。

4.2.7 编辑CSS

   先读取模板CSS,然后就可以修改其内容,并且系统给出CSS的简单说明书;然后点确定按钮,完成对CSS的编辑。实现这个功能部分代码如下:

    //得到模板文件

reportFile = Constant.getAPLICATIONDIR()

+ "Files";

Preferences preferences = new ConfigurationScope()

.getNode("com.XautReportDesign.product");

reportName = preferences.get("name", "report1");

deployDirectry = preferences.get("deployDirectry", reportFile);

cssFile = new File(deployDirectry + "/" + reportName + ".css");

  Composite comp = (Composite) super.createDialogArea(parent);

 //提示说明部分,简单吧?

Label label = new Label(parent, SWT.NONE);

label.setText("设置表格的CSS(已写部分,可以舔加)\nbody代表页面体\n#header代表报表作者时间\n#intro代表报表说明\n"

+ "table代表表格\n#tableheader代表表头\n#tabledanyuan代表单元格\n#footer代表页码");

//以下是把模板文件内容写入文本框的过程

cssText = new Text(comp, SWT.WRAP | SWT.H_SCROLL | SWT.V_SCROLL);

if (cssFile.isFile()) {

try {

fis = new FileReader(cssFile);

} catch (FileNotFoundException e) {

e.printStackTrace();

}

} else {

try {

fis = new FileReader(new File(deployDirectry + "/"

+ "style.css"));

} catch (FileNotFoundException e) {

e.printStackTrace();

}

}

char[] char1 = new char[2048];

try {

fis.read(char1, 0, char1.length);

} catch (IOException e) {

e.printStackTrace();

}

cssText.setText(new String(char1));

try {

fis.close();

} catch (IOException e) {

e.printStackTrace();

}

cssText.setSize(300, 300);

return parent;

4.2.8 生成模板

为了生成模板,要把当前编辑报表的CSS文件用不同的名称保存,并生成一个文本说明文件。但是CSS包括页面美观用的CSS,也有打印用的CSS,决定打印格式,所以编码就得多一步,代码如下所示:

File printcssFile = new File(deployDirectry + "/print" + reportName + ".css");

if (cssFile.isFile()) {

try {

fis = new FileInputStream(printcssFile);

} catch (FileNotFoundException e) {

e.printStackTrace();

}

}

else{

printcssFile = new File(deployDirectry + "/print" + reportName + ".css");

 try {

fis = new FileInputStream(printcssFile);

} catch (FileNotFoundException e) {

e.printStackTrace();

}

}

try {

fos = new FileOutputStream(new File(dir + "Template/print"

+ tempName.getText().trim() + ".css"));

} catch (FileNotFoundException e) {

e.printStackTrace();

}

try {

while (fis.read(b) != -1) {

fos.write(b);

}

} catch (IOException e) {

e.printStackTrace();

}

try {

fos.close();

fis.close();

} catch (IOException e) {

e.printStackTrace();

}

4.2.9 报表保存

    保存报表最主要的难点在于遍历表格,要读取数据和属性,还要记住各个单元格的ID,并按一定顺序写入xml文件。本系统用如下代码实现:

    public void run() {

if (workbenchWindow == null) {

return;

}

Preferences preferences = new ConfigurationScope()

.getNode("com.XautReportDesign.product");

String reportName = preferences.get("name", "report1");

String tempname = preferences.get("tempname", "Template");

String rownum = preferences.get("rownum", "15");

File reportFile = null;

try {

reportFile = new File(FileLocator.toFileURL(

Platform.getBundle("XautReportDesign").getEntry(""))

.getPath().toString()

+ "Files/" + reportName + ".xml");

} catch (IOException e) {

e.printStackTrace();

}

if (reportFile.isFile()) {

reportFile.delete();

}

Document document = DocumentHelper.createDocument();

Element reportDocument = document.addElement("XautReportFile");

reportDocument.addAttribute("Name", reportName);

reportDocument.addAttribute("tempname",tempname);

reportDocument.addAttribute("rownum", rownum);

reportDocument.addElement("Columns");

doJob("读表格内容");

IViewPart vp = workbenchWindow.getActivePage()

.findView(editAreaView.ID);

editAreaView eav = (editAreaView) vp;

Table table = eav.getTable();

TableItem item = null;

for (int i = 0; i < 7; i++) {

item = table.getItem(i);

for (int k = 1; k < 11; k++) {

String TableValue = item.getText(k);

if (TableValue != null || !TableValue.equals("")) {

int n = 0;

try {

n = TableValue.indexOf("@");

} catch (Exception e) {

e.printStackTrace();

}

String DataSource = null;

if (n != -1) {

Element column = reportDocument.element("Columns")

.addElement("Column");

String colName = String.valueOf((char) (64 + k))

+ String.valueOf(i + 1);

column.addText(colName);

try {

DataSource = TableValue.substring(0, n);

} catch (Exception e) {

e.printStackTrace();

}

column.addAttribute("DataSource", DataSource);

column.addAttribute("Span", TableValue.substring(n + 1,

n + 4));

column.addAttribute("Arrange", TableValue

.substring(n + 5));

column.addAttribute("Color", item.getBackground(k)

.getRGB().toString());

FontData[] fontData=item.getFont(k).getFontData();

column.addAttribute("Font",fontData[0].getName()+"."+fontData[0].getHeight()+"."+fontData[0].getStyle());

if (item.getImage(k) != null) {

column.addAttribute("Image", item.getText(k));

}

}

}

}

}

doJob("读入文件");

OutputFormat format = OutputFormat.createPrettyPrint();

format.setEncoding("GBK");

XMLWriter writer = null;

try {

writer = new XMLWriter(new FileWriter(reportFile), format);

writer.write(document);

} catch (IOException e1) {

e1.printStackTrace();

}

try {

writer.close();

} catch (IOException e1) {

e1.printStackTrace();

}

setEnabled(false);

  

4.2.10  配置服务器

   用户及系统开发人员可以在系统中控制Tomcat,这有很重要的价值,其代码如下:

     protected Control createDialogArea(Composite parent) {

Composite comp = (Composite) super.createDialogArea(parent);

comp.setLayout(new GridLayout(2, false));

root = document.getRootElement();

service = root.element("Service");

List<Element> nodes = service.elements("Connector");

Iterator<Element> it = nodes.iterator();

Connector = it.next();

new Label(comp, SWT.NONE).setText("设置端口");

port = new Text(comp, SWT.NONE);

port.setText(Connector.attributeValue("port"));

GridData grid1=new GridData();

grid1.widthHint=70;

grid1.heightHint=25;

port.setLayoutData(grid1);

new Label(comp, SWT.NONE).setText("设置最大线程数");

GridData grid2=new GridData();

grid2.widthHint=50;

grid2.heightHint=25;

maxThread = new Text(comp, SWT.NONE);

maxThread.setText(Connector.attributeValue("maxThreads"));

new Label(comp, SWT.NONE).setText("设置发布目录");

maxThread.setLayoutData(grid2);

engine = service.element("Engine");

deployDir = new Text(comp, SWT.NONE);

host = engine.element("Host");

GridData grid3=new GridData();

grid3.widthHint=150;

grid3.heightHint=25;

deployDir.setText(host.attributeValue("appBase"));

deployDir.setLayoutData(grid3);

new Label(comp, SWT.NONE).setText("选择发布目录");

Button btn1 = new Button(comp, SWT.NONE);

btn1.addSelectionListener(new SelectionListener() {

public void widgetDefaultSelected(SelectionEvent e) {

}

public void widgetSelected(SelectionEvent e) {

DirectoryDialog dialog = new DirectoryDialog(shell);

dialog.setText("目录");

dialog.setMessage("选择一个发布目录");

dialog.setFilterPath("c:/");

String dir = dialog.open();

if (dir != null) {

deployDir.setText(dir);

}

}

});

return parent;

}

protected void buttonPressed(int buttonId) {

if (buttonId == 0) {

Connector.attribute("port").setText(port.getText());

Connector.attribute("maxThreads").setText(maxThread.getText());

host.attribute("appBase").setText(deployDir.getText());

XMLWriter writer=null;

try {

writer = new XMLWriter(new FileWriter(Constant.SERVERCONFIFILE));

} catch (IOException e) {

e.printStackTrace();

}

try {

writer.write(document);

} catch (IOException e) {

e.printStackTrace();

}

try {

writer.close();

} catch (IOException e) {

e.printStackTrace();

}

close();

}else

close();

}

上面采用自定义对话框方法。首先读取配置文件的参数,然后显示出来,上面的createDialogArea()方法就示把参数显示在对话框体。而buttonPressed()方法就是点击确定后把参数写入配置文件。这里用到了DOM4J,其实本系统许多地方也用到了它,其用法与此处类似。

第五章 系统典型界面

5.1系统主界面

本系统主界面如图5-1所示,它包括菜单栏、工具栏,还有四个视图:编辑视图,就是有表格,占最大地方的;属性视图,在编辑视图下方;服务器视图、数据源视图在左边,两个采用重叠方式,这样节省空间。

   

图5-1 系统主界面图

5.1.1 编辑视图界面

                    图5-2 编辑视图界面

可以看出,图5-1的界面和EXCEL界面很相似,而且还表明当前编辑哪个报表。这些全是用SWT做出来的,可见JAVA可以开发很优秀的界面。

5.1.2  属性视图界面

                       图5-3 属性视图界面

是处于编辑状态的属性视图界面。可以看出当前正在编辑B1单元格。可以设置的属性有数据源、图像、颜色、字体等。这些都不需要自己动手写,可以从下拉或弹出菜单中选择,具有很高的效率。

5.1.3  服务器视图界面

               图5-4 服务器视图界面

发布到服务器目录的可以是pdf,xml,xls文件。在这个视图中可以启动、关闭服务器,并显示当前服务器的关键参数,这具有很高的实用性。

5.1.4  数据源视图界面

                    

                   图5-5数据源主界面

这个视图显示当前的数据源,并给出数据源的列。它采用树形的方式显示,用到了MVC设计模式。

5.2部分功能界面

本系统许多功能需要用到界面,其中大部分以对话框的形式出现。这些界面对系统功能实现带来了很大的好处,减轻了系统使用难度。

5.2.1 新建报表界面

           图5-6 新建报表界面

 

任何人看到这个对话框,就知道什么创建一个报表。

5.2.2 新建数据源界面

            图5-7建数据源界面

通过上面这个界面,可以看到,对于新建数据源,用户只需要选择数据库,并填写一些信息,就可以连接数据库。

5.2.3 设置CSS界面

       图5-8编辑CSS界面

   从下图可知,设置CSS并不像想像中那样难。在这里,你只需要有美术细胞,你就可以设计出页面好看的报表。图中的各个标记已经对WEB页面中的标记,提示部分说明了这种对应关系。

5.2.4 设置服务器参数界面

             图5-9设置服务器参数界面

如图所示,可以对服务器设置端口、发布目录、最大线程数。本例中的webapps是相对于应用服务器的主目录,也可以设置为其它绝对目录。可以单击下面按钮选择发布目录。

5.2.5 设置报表参数界面

      图5-10 设置服务器参数界面

在上面的图中,可以设置相关报表的各种额外参数,这些参数是报表中经常用到的。在最后一个文本框中可以输入报表说明,虽然看起来很小,但具有伸缩功能。

5.2.6生成模板界面

       图5-11生成模板界面

在上面对话框中,可以设置模板名及说明文字,然后点确定,一个模板文件就生成。

第六章 课题总结

我本次毕业设计的主要任务是基于JAVA开发报表设计器。报表的功能要求WEB访问,能用CSS编辑页面、页码、打印,生成模板,生成PDF、XML,够吓人的吧!这东西对我来说是很难的,我在大学期间最多开发一些简单的MIS系统。但经过三个月的奋斗,我的报表设计器终于按照设计的格式工作了。虽然和那些商业报表比起来差多了,但这毕竟是我一个未出校的本科生完成的。以下是我的收获:

第一,很好地掌握了Eclipse RCP开发。JAVA很有用,但很少用在桌面系统。但IBM推出SWT后,情况就不一样了,特别是在有Eclipse RCP技术后,越来越多的领域采用RCP技术,我今后工作的公司很可能已经使用了。为开发这个系统,我全部看了三本RCP方面的书,这些书总共有1300多页!可以说,现在我可以很轻松用Eclipse RCP技术开发一个系统。

第二,更加熟练地使用JAVA。虽然是采用Eclipse RCP开发,但必须有JAVA基础。开发本系统,使我熟练了Eclipse各种用法,掌握安装插件方法,掌握使用第三方JAR包方法,掌握许多常用的设计模式,掌握常用服务器的用法。现在我可以很熟练地用JAVA开发网站,也能开发桌面系统。

第三,掌握了许多文件类型和数据库。本系统用到CSS、XML、PDF、XLS,对于这些文件,我专门进行了研究,现在已经很熟练操作。而为测试本报表,我用到了SQLSERVER 2005、MYSQL5.5、ACCESS,这些数据库我都能比较熟练使用

第四,学会勇敢面对困难。报表设计器开发,这个我以前没听说过,感觉难度太大。后来又想,就要出去工作了,以后会有更加难的工作,现在就当训练机会。在整个开发过程中,我看完了三本450页以上的书,到101机房的出勤率90%以上。这些努力使我的开发按时完成了。

第五,掌握了更有效的学习方法。为开发本系统,我用到许多技术,许多是以为没听说过的。在开发过程中,我积极利用图书馆,网络找到这些技术有用于本系统的地方,并把这些资料专门存放在一个文件夹,供以后使用。

 由于时间有限,系统还有许多不尽如人意的地方,比如报表格式太简单;解析报表也太过简单;表格编辑能力太弱,得用EXCEL补充编辑;有许多菜单没完成;生成PDF、EXCEL、WEB三种格式是相互独立的,只能从EXCEL到WEB转换,其它之间不能转等。以后有空,我会补充完成,发到网上,可以提供给学习RCP的人一个例子。

致谢

在整个毕业设计过程中, 张璟老师给予了我耐心的指导、无私的帮助,并且为我提供了良好的学习环境, 帮助我顺利完成论文及答辩。他渊博的知识、严谨的治学态度和谦和的待人风范使我受益匪浅,在此我对张老师致以深深的谢意!

另外,感谢研究生赵晓辉在技术上给我的帮助;感谢刘东同学的支持及指导,并提供各种资料;感谢范道健,他在一些关键代码调试提供帮助;感谢实验室老师,他们每天按时开门,使我可以在最快时间进入工作。

参考文献

[1].那静著. Eclipse SWT/JFace核心应用. 北京:清华大学出版社,2007年3月.

[2]. 强锋科技, 陈刚著.Eclipse从入门到精通(第二版). 北京:清华大学出版社,2007年7月

[3]. 陈刚著.Eclipse RCP应用系统开发方法与实战. 北京:电子工业出版社,2007年7月

[4]. 马斗,邱哲 王俊标著.专家门诊/JSP开发答疑200问. 北京:人民邮电出版社,2005年10月

[5]. 甘树满,王秀明著. Eclipse插件开发方法与实战. 北京:电子工业出版社,2006年10月

[6]. )Berthold Daum. Eclipse3高级编程.李化,李政仪译.北京:清华大学出版社,2006年6月

[7].(美)迈耶Daum著. CSS权威指南. 尹志忠,侯妍译. 北京:中国电力出版社,2007年10月

[8]. James W.Cooper著. JAVA设计模式. 龚波,赵彩琳,陈蓓译.北京:中国电力出版社,2003年10月

[9]. Herbert Schildt,James Holmes. Java编程艺术.邓劲生译.北京:清华大学出版社,2004年9月

[10]. (美)Alistair Cockburn著. 敏捷软件开发(第2版). 苏敬凯译.北京:机械工业出版社,2008年3月

附录

                                   (英文翻译)

Rich Client Tutorial Part 1

The Rich Client Platform (RCP) is an exciting new way to build Java applications that can compete with native applications on any platform. This tutorial is designed to get you started building RCP applications quickly. It has been updated for Eclipse 3.1.2

By Ed Burnette, SAS
July 28, 2004
Updated for 3.1.2: February 6, 2006


Introduction

Try this experiment: Show Eclipse to some friends or co-workers who haven't seen it before and ask them to guess what language it is written in. Chances are, they'll guess VB, C++, or C#, because those languages are used most often for high quality client side applications. Then watch the look on their faces when you tell them it was created in Java, especially if they are Java programmers.

Because of its unique open source license, you can use the technologies that went into Eclipse to create your own commercial quality programs. Before version 3.0, this was possible but difficult, especially when you wanted to heavily customize the menus, layouts, and other user interface elements. That was because the "IDE-ness" of Eclipse was hard-wired into it. Version 3.0 introduced the Rich Client Platform (RCP), which is basically a refactoring of the fundamental parts of Eclipse's UI, allowing it to be used for non-IDE applications. Version 3.1 updated RCP with new capabilities, and, most importantly, new tooling support to make it easier to create than before.

If you want to cut to the chase and look at the code for this part you can find it in the accompanying zip file. Otherwise, let's take a look at how to construct an RCP application.

Getting started

RCP applications are based on the familiar Eclipse plug-in architecture, (if it's not familiar to you, see the references section). Therefore, you'll need to create a plug-in to be your main program. Eclipse's Plug-in Development Environment (PDE) provides a number of wizards and editors that take some of the drudgery out of the process. PDE is included with the Eclipse SDK download so that is the package you should be using. Here are the steps you should follow to get started.

First, bring up Eclipse and select File > New > Project, then expand Plug-in Development and double-click Plug-in Project to bring up the Plug-in Project wizard. On the subsequent pages, enter a Project name such as org.eclipse.ui.tutorials.rcp.part1, indicate you want a Java project, select the version of Eclipse you're targeting (at least 3.1), and enable the option to Create an OSGi bundle manifest. Then click Next >.

Beginning in Eclipse 3.1 you will get best results by using the OSGi bundle manifest. In contrast to previous versions, this is now the default.

In the next page of the Wizard you can change the Plug-in ID and other parameters. Of particular importance is the question, "Would you like to create a rich client application?". Select Yes. The generated plug-in class is optional but for this example just leave all the other options at their default values. Click Next > to continue.

If you get a dialog asking if Eclipse can switch to the Plug-in Development Perspective click Remember my decision and select Yes (this is optional).

Starting with Eclipse 3.1, several templates have been provided to make creating an RCP application a breeze. We'll use the simplest one available and see how it works. Make sure the option to Create a plug-in using one of the templates is enabled, then select the Hello RCP template. This is RCP's equivalent of "Hello, world". Click Finish to accept all the defaults and generate the project (see Figure 1). Eclipse will open the Plug-in Manifest Editor. The Plug-in Manifest editor puts a friendly face on the various configuration

files that control your RCP application.

Figure 1. The Hello World RCP project was created by a PDE wizard.

Taking it for a spin

Trying out RCP applications used to be somewhat tedious. You had to create a custom launch configuration, enter the right application name, and tweak the plug-ins that were included. Thankfully the PDE keeps track of all this now. All you have to do is click on the Launch an Eclipse Application button in the Plug-in Manifest editor's Overview page. You should see a bare-bones Workbench start up (see Figure 2).

Figure 2. By using the templates you can be up and running an RCP application in minutes.

Making it a product

In Eclipse terms a product is everything that goes with your application, including all the other plug-ins it depends on, a command to run the application (called the native launcher), and any branding (icons, etc.) that make your application distinctive. Although as we've just seen you can run a RCP application without defining a product, having one makes it a whole lot easier to run the application outside of Eclipse. This is one of the major innovations that Eclipse 3.1 brought to RCP development.

Some of the more complicated RCP templates already come with a product defined, but the Hello RCP template does not so we'll have to make one.

In order to create a product, the easiest way is to add a product configuration file to the project. Right click on the plug-in project and select New > Product Configuration. Then enter a file name for this new configuration file, such as part1.product. Leave the other options at their default values. Then click Finish. The Product Configuration editor will open. This editor lets you control exactly what makes up your product including all its plug-ins and branding elements.

In the Overview page, select the New... button to create a new product extension. Type in or browse to the defining plug-in (org.eclipse.ui.tutorials.rcp.part1). Enter a Product ID such as product, and for the Product Application select org.eclipse.ui.tutorials.rcp.part1.application. Click Finish to define the product. Back in the Overview page, type in a new Product Name, for example RCP Tutorial 1.

In Eclipse 3.1.0 if you create the product before filling in the Product Name you may see an error appear in the Problems view. The error will go away when you Synchronize (see below). This is a known bug that is fixed in newer versions. Always use the latest available maintenance release for the version of Eclipse you're targeting!

Now select the Configuration tab and click Add.... Select the plug-in you just created (org.eclipse.ui.tutorials.rcp.part1) and then click on Add Required Plug-ins. Then go back to the Overview page and press Ctrl+S or File > Save to save your work.

If your application needs to reference plug-ins that cannot be determined until run time (for example the tomcat plug-in), then add them manually in the Configuration tab.

At this point you should test out the product to make sure it runs correctly. In the Testing section of the Overview page, click on Synchronize then click on Launch the product. If all goes well, the application should start up just like before.

Plug-ins vs. features

On the Overview page you may have noticed an option that says the product configuration is based on either plug-ins or features. The simplest kind of configuration is one based on plug-ins, so that's what this tutorial uses. If your product needs automatic update or Java Web Start support, then eventually you should convert it to use features. But take my advice and get it working without them first.

Running it outside of Eclipse

The whole point of all this is to be able to deploy and run stand-alone applications without the user having to know anything about the Java and Eclipse code being used under the covers. For a real application you may want to provide a self-contained executable generated by an install program like InstallShield or NSIS. That's really beyond the scope of this article though, so we'll do something simpler.

The Eclipse plug-in loader expects things to be in a certain layout so we'll need to create a simplified version of the Eclipse install directory. This directory has to contain the native launcher program, config files, and all the plug-ins required by the product. Thankfully, we've given the PDE enough information that it can put all this together for us now.

In the Exporting section of the Product Configuration editor, click the link to Use the Eclipse Product export wizard. Set the root directory to something like RcpTutorial1. Then select the option to deploy into a Directory, and enter a directory path to a temporary (scratch) area such as C:\Deploy. Check the option to Include source code if you're building an open source project. Press Finish to build and export the program.

The compiler options for source and class compatibility in the Eclipse Product export wizard will override any options you have specified on your project or global preferences. As part of the Export process, the plug-in is code is recompiled by an Ant script using these options.

The application is now ready to run outside Eclipse. When you're done you should have a structure that looks like this in your deployment directory:

    RcpTutorial1

    |    .eclipseproduct

    |    eclipse.exe

    |    startup.jar

    +--- configuration

    |         config.ini

    +--- plugins

              org.eclipse.core.commands_3.1.0.jar

              org.eclipse.core.expressions_3.1.0.jar

              org.eclipse.core.runtime_3.1.2.jar

              org.eclipse.help_3.1.0.jar

              org.eclipse.jface_3.1.1.jar

              org.eclipse.osgi_3.1.2.jar

              org.eclipse.swt.win32.win32.x86_3.1.2.jar

              org.eclipse.swt_3.1.0.jar

              org.eclipse.ui.tutorials.rcp.part1_1.0.0.jar

              org.eclipse.ui.workbench_3.1.2.jar

              org.eclipse.ui_3.1.2.jar

Note that all the plug-ins are deployed as jar files. This is the recommended format starting in Eclipse 3.1. Among other things this saves disk space in the deployed application.

Previous versions of this tutorial recommended using a batch file or shell script to invoke your RCP program. It turns out this is a bad idea because you will not be able to fully brand your application later on. For example, you won't be able to add a splash screen. Besides, the export wizard does not support the batch file approach so just stick with the native launcher.

Give it a try! Execute the native launcher (eclipse or eclipse.exe by default) outside Eclipse and watch the application come up. The name of the launcher is controlled by branding options in the product configuration.

Troubleshooting

Error: Launching failed because the org.eclipse.osgi plug-in is not included...

You can get this error when testing the product if you've forgotten to list the plug-ins that make up the product. In the Product Configuration editor, select the Configuration tab, and add all your plug-ins plus all the ones they require as instructed above.

Compatibility and migration

If you are migrating a plug-in from version 2.1 to version 3.1 there are number of issues covered in the on-line documentation that you need to be aware of. If you're making the smaller step from 3.0 to 3.1, the number of differences is much smaller. See the References section for more information.

One word of advice: be careful not to duplicate any information in both plug-in.xml and MANIFEST.MF. Typically this would not occur unless you are converting an older plug-in that did not use MANIFEST.MF into one that does, and even then only if you are editing the files by hand instead of going through the PDE.

Conclusion

In part 1 of this tutorial, we looked at what is necessary to create a bare-bones Rich Client application. The next part will delve into the classes created by the wizards such as the WorkbenchAdvisor class. All the sample code for this part may be found in the accompanying zip file.

References

RCP Tutorial Part 2 
RCP Tutorial Part 3 
Eclipse Rich Client Platform 
RCP Browser example (project org.eclipse.ui.examples.rcp.browser) 
PDE Does Plug-ins 
How to Internationalize your Eclipse Plug-in 
Notes on the Eclipse Plug-in Architecture 
Plug-in Migration Guide: Migrating to 3.1 from 3.0 
Plug-in Migration Guide: Migrating to 3.0 from 2.1

译文:

Rich Client教程第一部分

The Rich Client Platform (RCP)是一种创建Java应用程序的令人兴奋的新方法,可以和任何平台下的自带应用程序进行竞争。这个教程会使你较快学会创建RCP应用程序,已更新到Eclipse 3.1.2版本

作者: Ed Burnette, SAS

July 28, 2004

更新到3.1.2: February 6, 2006

介绍

试试这样的试验:展示Eclipse给一些以前从来没有看见过它的朋友或同事,并让他们猜测一下它是用什么语言编写的。很大可能,他们会猜VB, C++, or C#,因为那些语言通常用于优质客户端应用程序。告诉他们这是用Java编制的,看看他们的表情,尤其他们是java程序员的话。

因为它独一无二的开放源码许可的缘故,你可以使用Eclipse生成你自己的商用的优质程序。在3.0以前的版本,这样是可能的但是非常的麻烦,特别当你想要着重个性化设计菜单,编排,以及其他的用户接口部分。主要是由于Eclipse 的“集成电路设备”固化。3.0版本引入了the Rich Client Platform (RCP),主要基于Eclipse的用户界面基本部分进行了重新分解。3.1版本对RCP进行了一些新特性的更新,并且最重要的是,通过新工具的支持使它比以前更加容易创建。

如果你想直接跳到重点,看这部分的代码你可以在accompanying zip file.里找到。否则的话,让我们看看怎样构建一个RCP。

开始

RCP应用程序是基于熟悉的Eclipse插件结构,(如果你对这部分不熟悉的话,请看参考书目部分)。因此,你将需要创建一个插件程序成为你的主程序。Eclipse的插件发展环境(PDE)提供大量的向导和编辑器,负担了创建中的一些苦工。PDE包含在了你将使用的Eclipse SDK下载包里。现在跟着一下步骤开始。

首先,打开Eclipse,选择File > New > Project,然后展开Plug-in Development,双击Plug-in Project来打开Plug-in Project 向导。在接下来的页面上,输入一个项目的名字,例如org.eclipse.ui.tutorials.rcp.part1,说明你想要一个Java 项目,选择你需要的Eclipse版本,并且勾选Create an OSGi bundle manifest选项。然后单击Next

插图一. PDE向导创建的The Hello World RCP 项目

换一个角度理解

试用RCP应用程序通常有些单调乏味。你不得不生成一个定制的首次配置,输入正确的应用程序名称,并且管理调整所有包含的插件。非常感激PDE现在保存所有这些记录。你全部需要做的只是单击Manifest编辑器总览页上的Eclipse 应用程序按钮。你将看到一个简单的工作台页面跳出来(见插图二)。

插图二. 使用模板,你可以在几分钟之内创建运行一个RCP应用程序

创建一个产品

对于Eclipse来说,一个产品是你的应用程序及所伴随的所有相关设置,包括它依靠的所有其他插件,用来运行程序的命令(称为自带的发射台),和一些使你的产品与众不同的商标(标记,等等)。虽然我们只在意你可以不需要定义一个产品来运行RCP应用程序,使不依赖Eclipse而运行一个应用程序更加轻松简单。引入RCP开发这是Eclipse 3.1版本的主要创新。

一些更加复杂的RCP模板已经和产品一起定义了,但是Hello RCP 模板没有带,所以我们将需要定义一个。

为了创建一个产品,最简单的方法是给项目增加一个产品配置文件,在plug-in项目上右键单击,选择New > Product Configuration。接下来,给这个这个新配置文件输入一个文件名,例如part1.product。保留余下的选择和默认值一致。

然后单击Finish。 产品配置编辑器将会打开。这个编辑器允许你严密的控制构成你产品的所有plug-ins和商标元素

在总览页面,选择New... 按钮来创建一个新的产品扩展名。输入或者使用浏览方式找到定义的plug-in(org.eclipse.ui.tutorials.rcp.part1)。输入一个产品ID, 例如product,对应的产品应用程序选择org.eclipse.ui.tutorials.rcp.part1.application.。单击Finish 来完成定义产品。回到总览页面,输入一个新的产品名称,比如RCP Tutorial 1。

在Eclipse 3.1.0版本,如果你在填入产品名称之前创建一个产品,你可能会看见一个出错信息出现在问题视窗。当你同步的时候,出错信息将会消失(见后面)。这是一个已知的缺陷,在后续版本作了修正。总是使用最新修正可用的Eclipse版本

现在选择配置标签,并且单击Add…,选择你前面所创建的插件程序(org.eclipse.ui.tutorials.rcp.part1),然后单击Add Required Plug-ins,回到总览页面,按住Ctrl+S,或者选择File > Save来保存你的工作。

如果你的应用程序需要涉及的plug-ins直到运行的时候才能决定(例如:tomcat plug-in),那就在配置表标签内手动增加。

到这个阶段,你应该测试产品确认它运行正常。在总览页面的测试部分,单击同步,然后单击运行产品。如果一切顺利,应用程序窗口应该像先前一样跳出来。

依赖插件还是依赖特性

在总览页面,你可能注意到一个选项关于:产品的配置是基于插件或特性两者任何一个。这种最简单的配置是一种基于插件,这个教程所用的。如果你的产品需要自动升级或java网站的初始支持,那么最终你需要将它转换成特性。但是请接受我的建议,先在不使用特性情况下使它工作

在Eclipse环境外运行

最重要的观点是:配置和运行一个独立的应用程序,不需要用户知道任何封装起来的Java 和 Eclipse代码。对于一个真正的应用程序,你可能想要提供通过安装程序例如InstallShield 或者NSIS一个完整执行包。这个远远超过了这篇文章的范围,因此我们只作简单介绍。

Eclipse插件导入装置期望事件按某种规划执行,因此我们需要创建一个简单版本的Eclipse 安装目录。这个目录必须包含自带的启动程序,设置文件,和产品需要的全部插件。幸好,我们给予PDE足够的信息,现在它可以为我们将这些组织起来。

在产品配置编辑器的输出部分,单击使用Eclipse 输出向导的连接。设定根目录类似RcpTutorial1。然后选择展开目录的选项,输入一个目录路径到一个临时(草稿)区域比如C:\Deploy 。如果你建立了一个开放源码项目,勾选包含源代码选项。按Finish 来建立和输出这个程序。

在Eclipse产品输出向导中的源码和类兼容性编辑器选项可能会无视你在你的项目中特别指定的选项或全局参数。作为输出进程的一部分,插件是被使用这些选项的Ant script重新编译的代码

应用程序现在可以在Eclipse 之外运行了。当你完成的时候,在你的开发目录里。你应该有个看起来像下面这样的结构:

    RcpTutorial1

    |    .eclipseproduct

    |    eclipse.exe

    |    startup.jar

    +--- configuration

    |         config.ini

    +--- plugins

              org.eclipse.core.commands_3.1.0.jar

              org.eclipse.core.expressions_3.1.0.jar

              org.eclipse.core.runtime_3.1.2.jar

              org.eclipse.help_3.1.0.jar

              org.eclipse.jface_3.1.1.jar

              org.eclipse.osgi_3.1.2.jar

              org.eclipse.swt.win32.win32.x86_3.1.2.jar

              org.eclipse.swt_3.1.0.jar

              org.eclipse.ui.tutorials.rcp.part1_1.0.0.jar

              org.eclipse.ui.workbench_3.1.2.jar

              org.eclipse.ui_3.1.2.jar

所有的插件的扩展看起来像jar文件。这是一个在Eclipse 3.1版本里推荐的格式化开始。在配置程序里节省磁盘空间的方式之一。

这个教程的先前版本推荐使用一个批处理文件或外壳程序来调用你的RCP程序。它被证明是一个糟糕的主意,因为如果你随后将不能在你的应用程序上打上完全属于你的标记。比如,你将不能增加一个splash screen。此外,输出向导不支持批处理文件方式,只是继续自带的初始程序。

试试看!在Eclipse环境外,执行自带的初始程序(默认的eclipse 或 eclipse.exe ) ,看看应用程序运行起来。初始程序的名字受到产品配置商标选项的约束。

排除错误

错误:初始失败,由于org.eclipse.osgi 插件没有被包含... 当测试产品的时候你忘记列出组成产品的插件,你将得到以上错误信息。在产品配置编辑器内,选择配置标签,增加你的所有插件并在插件中加上上面要求的部分。

兼容性和移植性

如果你将2.1版本的plug-in 移植到3.1版本,在线文档里涵盖了一大堆你需要知道的问题。如果你仅仅是3.0到3.1一小步的话,差异的数量就小了很多。了解更多信息请见参考书目部分。

一句忠告:小心不要在plug-in.xml 和 MANIFEST.MF两个里复写任何信息。正常地,这种情况是不会发生的,除非你将一个旧的plug-in转换成目前需要用MANIFEST.MF的plug-in,甚至尽管你仅仅用手工编辑那些文件而不是通过PDE 。

结束

在教程的第一部分,我们考虑创建一个Rich Client应用程序的必要步骤。下一个部分将深入研究由向导生成的类,比如工作台类。这部分的例子代码可以在附加的zip文件里找到。

参考书目

RCP Tutorial Part 2 
RCP Tutorial Part 3 
Eclipse Rich Client Platform 
RCP Browser example (project org.eclipse.ui.examples.rcp.browser) 
PDE Does Plug-ins 
How to Internationalize your Eclipse Plug-in 
Notes on the Eclipse Plug-in Architecture 
Plug-in Migration Guide: Migrating to 3.1 from 3.0 
Plug-in Migration Guide: Migrating to 3.0 from 2.1

  • 21
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等天晴i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值