文件ipage

ipage  时间:2021-01-02  阅读:()

第1章Eclipse简介81.
1Eclipse的历史81.
2Eclipse的体系结构81.
3优秀的图形API:SWT/JFace.
91.
4开放式、可扩展的IDE.
101.
5全中文化的帮助文件101.
6Eclipse是开放源代码的111.
7本章小结11第2章安装Eclipse及多国语言包122.
1安装JDK.
122.
2安装Eclipse.
122.
3Eclipse多国语言包的安装142.
4本章小结16第3章安装SWTDesigner173.
1下载173.
2安装173.
3注册激活183.
4其他常用插件203.
5本章小结21第4章Eclipse的集成开发环境224.
1Eclipse界面简介224.
2创建Java项目并运行234.
3自定义注释及代码格式化274.
3.
1自定义注释274.
3.
2代码格式化294.
3.
3实践建议304.
4使用Eclipse的重构功能304.
5任务标记314.
5.
1任务标记的设定314.
5.
2过滤任务标记324.
6在编程时随意查看JDK、Eclipse源代码334.
6.
1查看JDK源代码334.
6.
2查看Eclipse的源代码344.
7在代码中搜索364.
8打开类型层次结构374.
9调试器的使用384.
10常用快捷键394.
11本章小结40第5章Eclipse中CVS的使用415.
1CVS简介415.
2CVS服务器端的安装与配置415.
3CVS客户端的配置435.
4文件提交与更新的方法485.
4.
1CVS和VSS的不同之处485.
4.
2文件的提交和更新485.
4.
3解决文件提交的冲突505.
4.
4如何忽略掉不想提交的文件515.
4.
5实践建议525.
5在CVS上为软件打包一个版本525.
6将项目替换成CVS上的其他版本535.
7修改过去版本的BUG.
.
545.
8本章小结55第6章SWT概述566.
1SWT简介566.
2SWT中的包566.
3用SWTDesigner写一个HelloWorld.
576.
4关于SWT/JFace例程的说明646.
5实践建议656.
6本章小结65第7章SWT/JFace的事件模型667.
1事件的四种写法667.
2常用事件介绍687.
3在事件代码中如何访问类中的变量687.
3.
1访问类中的变量的三种方法687.
3.
2Java中变量的称法和说明697.
4本章小结70第8章SWT常用组件718.
1按钮、复选框、单选框(Button类)718.
2组件的常用方法728.
3标签(Label类)738.
4文本框(Text类)748.
5下拉框(Combo类)768.
6列表框(List类)788.
7本章小结79第9章容器类809.
1面板(Composite类)809.
2分组框(Group类)809.
3选项卡(TabFolder类、TabItem类)819.
4分割窗(SashForm类)839.
5带滚动条的面板(ScrolledComposite类)849.
6本章小结86第10章布局管理器8710.
1布局管理器简介8710.
2充满式(FillLayout类)8710.
3行列式(RowLayout类)8910.
4网格式(GridLayout类)9210.
5堆栈式(StackLayout类)9810.
6表格式(FormLayout类)10010.
7布局的综合实例10310.
8本章小结108第11章其他SWT组件10911.
1工具栏(ToolBar类、ToolItem类、ViewForm类)10911.
2动态工具栏(CoolBar类、CoolItem类)11011.
3菜单(Menu类,MenuItem类)11311.
4滑动条(Slider类)、刻度条(Scale类)、进度条(ProgressBar类)11511.
5画布(Canvas类)11611.
6表格(Table类)11811.
7树(Tree类)11911.
8表格型树(TableTree类)12011.
9本章小结122第12章图像12312.
1图像(Image类)12312.
2图像(Image类)存在的问题12412.
3图像描述符(ImageDescriptor类)12412.
4图像注册表(ImageRegistry类)12512.
5本章小结126第13章SWT的线程12713.
1SWT线程简介12713.
2一个SWT线程的实例12713.
3对11.
4节进度条实例的改进13113.
4本章小结133第14章表格(TableViewer类)13414.
1前言13414.
2让数据在TableViewer中显示出来13414.
3TableViewer响应鼠标事件14014.
4加上右键菜单(Action类、ActionGroup类、MenuManager类)14114.
5TableViewer排序(ViewerSorter类)14314.
6加上工具栏(ToolBarManager类)14514.
7创建一个带复选框的TableViewer(CheckboxTableViewer类)14914.
8单击修改表格单元格值(CellEditor类、ICellModifier接口)15114.
9其他使用技巧15414.
10本章小结155第15章树(TreeViewer类)和列表(ListViewer类)15615.
1树简介15615.
2前期准备:实例所用数据模型说明15615.
3让数据在树中显示出来15815.
4给树加上右键菜单及取得结点的值16315.
5树结点的展开、收缩、新增、删除、修改16415.
6ListViewer简介16815.
7ListViewer的实例16815.
8ListViewer常用方法16915.
9本章小结169第16章对话框17016.
1对话框(Dialog类)17016.
1.
1对话框简介17016.
1.
2信息提示框(MessageDialog类)17116.
1.
3输入值对话框(InputDialog类)17216.
1.
4自定义对话框(Dialog类)17316.
1.
5对话框的设置与取值17716.
1.
6带提示栏的对话框(TitleAreaDialog类)17816.
2向导式对话框(WizardDialog类)17916.
2.
1向导式对话框简介17916.
2.
2向导式对话框实例18016.
2.
3向导式对话框使用的注意事项18416.
3进度条对话框(ProgressMonitorDialog类)18516.
3.
1进度条对话框简介18516.
3.
2进度条对话框实例18516.
4其他类型对话框18716.
4.
1信息提示框(MessageBox类)18716.
4.
2颜色选择对话框(ColorDialog类)18816.
4.
3字体选择对话框(FontDialog类)18816.
4.
4打印设置对话框(PrintDialog类)18916.
4.
5目录选择对话框(DirectoryDialog类)19316.
4.
6文件选择对话框(FileDialog类)19316.
5本章小结195第17章Eclipse插件开发起步19617.
1Eclipse插件开发概述19617.
2插件的HelloWorld.
19617.
2.
1使用向导一步步创建HelloWorld.
19617.
2.
2以空白项目为基础创建HelloWorld.
19917.
3本章小节203第18章常用插件扩展点20418.
1加入透视图(perspectives)20418.
2在透视图中加入视图(views)20618.
3在视图之间实现事件监听20818.
4给视图加下拉菜单和按钮21018.
5加入编辑器(editors)21218.
6编辑器类(EditorPart)方法使用说明21618.
7加入首选项(preferencePages)21918.
8加入帮助(toc)22418.
9弹出信息式的帮助(contexts)22618.
10本章小结228第19章Eclipse插件的国际化22919.
1国际化简介22919.
2为国际化创建一个插件的"段项目"22919.
3类程序的国际化23119.
4plugin.
xml的国际化23619.
5其他XML文件的国际化23719.
6使用"外部化字符串"向导23819.
7本章小结240第20章报表:用POI与Excel交互24120.
1POI概述24120.
1.
1POI简介24120.
1.
2POI的下载与安装24120.
2将数据导出成Excel的实例24420.
2.
1创建一个空白的Excel文件24420.
2.
2往Excel单元格中写入信息24420.
2.
3中文化的问题24520.
3使用式样24620.
3.
1日期式样及文字对齐式样24620.
3.
2边框式样24720.
3.
3背景色及底纹式样24820.
3.
4合并单元格24820.
3.
5字体式样24920.
4更多的用法24920.
4.
1设置页眉页脚24920.
4.
2冻结和分割窗25020.
4.
3浮动文字框及在表中画图25020.
4.
4设置打印的范围25120.
4.
5读取及修改Excel25120.
5本章小结252第21章项目打包与发行25321.
1应用程序项目的打包与发行25321.
1.
1简介25321.
1.
2打包的具体操作步骤25321.
1.
3其他得到JAR包的方式25721.
1.
4使用第三方插件对项目打包25821.
1.
5让用户电脑不必安装JRE环境26021.
1.
6更进一步的完善26021.
1.
7打包的其他说明26221.
2插件项目的打包与发行26321.
2.
1简介26321.
2.
2打包的具体操作步骤26321.
2.
3测试打包效果26521.
3用Ant来打包26621.
4本章小结271第22章插件项目实战篇27222.
1前期准备工作27222.
1.
1软件开发过程27222.
1.
2本章项目开发环境的选择27322.
1.
3安装MySQL.
27622.
1.
4在Eclipse插件中连接MySQL数据库(版本V0001)27922.
1.
5解决Java的中文问题28422.
1.
6对字符集设置的测试结果28622.
2面向对象分析和数据表创建(版本V0010)29222.
2.
1界面效果及实现功能29222.
2.
2面向对象的分析与设计29322.
2.
3创建数据表30122.
2.
4给数据表插入数据30522.
3创建项目的主界面框架30622.
3.
1前言30622.
3.
2创建透视图及主功能视图(版本V0020)30722.
3.
3创建"功能导航器视图"的树(版本V0020)31022.
3.
4创建项目的图像注册表(版本V0030)31422.
4用户登录、退出功能的实现(版本V0040)31722.
4.
1实现方案31722.
4.
2界面部份的源代码31822.
4.
3数据库部份的源代码32322.
4.
4小结32822.
5"档案管理"编辑器的实现32822.
5.
1前言32822.
5.
2编辑器的创建与排序、翻页功能的实现(版本V0050)32822.
5.
3实现删除用户功能(版本V0060)33922.
5.
4实现新增用户功能(版本V0060)34122.
5.
5实现修改用户的功能(版本V0070)35322.
6"成绩管理"编辑器的实现(版本V0080)35922.
6.
1前言35922.
6.
2单击结点打开视图35922.
6.
3实现搜索视图SearchView.
.
36022.
6.
4实现"成绩管理"编辑器36422.
7让软件适应多种数据库(版本V0090)36622.
7.
1前言36622.
7.
2解决方案36722.
7.
3具体实现的源代码36722.
8首选项的实现(版本V0100)36922.
8.
1前言36922.
8.
2首选项的源代码36922.
8.
3将程序中的设置值改成取之于首选项的设置37422.
9本章小结374第23章WEB环境的搭建(V0010)37523.
1前言37523.
2Tomcat的下载与安装37623.
3Lomboz的下载与安装37923.
4Lomboz的环境设置38123.
5JSP的HelloWorld.
38223.
6如何不必发布就可以在IE上显示WEB修改效果38623.
7配置Tomcat的数据库连接池38823.
8本章小结390第24章一个纯JSP+JavaBean实例(V0020)39124.
1JavaBean的环境配置39124.
2创建JavaBean及数据库层39124.
3编写前台的JSP文件39324.
4本章小结398第25章在Eclipse中使用Struts.
40025.
1前言40025.
2Struts的下载及安装(V0030)40025.
3Struts入门实例(V0030)40225.
3.
1Struts原理简介40225.
3.
2用户登录实例40425.
4让Dreamweaver支持struts标签41025.
5struts-config.
xml再深入41225.
5.
1页面转发41225.
5.
2项之动态ActionForm.
.
41325.
5.
3项41325.
5.
4使用DispatchAction类41425.
5.
5使用多个struts-config.
xml配置文件41525.
6验证的多种方法(V0040)41625.
6.
1方法一41625.
6.
2方法二41625.
7使用更多的struts标签42325.
7.
1获知更多的标签42325.
7.
2表单类标签42325.
7.
3其他说明42525.
8本章小结425第26章在Eclipse中使用Hibernate.
42626.
1前言42626.
2Hibernate的下载和安装(V0050)42726.
3一个简单的Hibernate实例(V0050)43126.
4继续深入使用Hibernate(V0060)43526.
5实现用户的修改、删除功能(V0070)44026.
6解决Tomcat的中文问题(V0070)44626.
7Hibernate的自动生成工具44726.
8本章小结4525.
1.
1Eclipse插件开发简介插件的概念读者应该很熟悉,象MP3播放软件WINAMP的皮肤插件、WindowsMediaPlayer的众多的外观插件、音效插件等等.
但如果你以为插件只能做成为原软件的边角料,那是可以理解的,因为你还没有看到过Eclipse的插件是什么样的.
Eclipse可以全面更新你对插件的概念,它也是对插件概念运用得最彻底最炉火纯青的一个软件.
在第一章我们就介绍了Eclipse的技术特点,Eclipse的内核很小,其他功能都是基于这个内核上的插件,如Eclipse自带的UNIT、ANT等.
而且Eclipse还开放了自己的插件机制,并提供了很好的插件开发环境,让用户可以自己来开发Eclipse的插件.
想知道开发Eclipse的插件能到什么程度吗看看这些Eclipse上的插件吧:用于UML建模的TogetherforEclipse、用于JSP的MyEclipse和Lomboz、IBM的全能开发工具WSAD等等,它们全是Eclipse的插件.
如果微软愿意,也可以把Office软件做成Eclipse的插件.
如果Adobe有兴趣,Photoshop也可以有forEclipse的插件版,Eclipse中的APIDraw2D的绘图功能也是很功的.
Eclipse的各式插件正如雨后春笋般不断冒出,Eclipse已经超越了开发环境的概念,它的目标是做成一个通用的平台,让尽量多的软件做为插件集成在上面,成为未来的集成的桌面环境.
同样我们可以将我们的应用系统写成Eclipse插件,笔者就在2004年参与开发了一个项目管理软件,该软件就是以Eclipse的插件形式开发的.
5.
1.
2Eclipse插件开发的优势和不足那么将软件写成插件有什么好处呢对于用户来说Eclipse的使用环境比较友好,前面介绍的SWT/JFace中还是比较基本的界面元素,象Eclipse中的视图、编辑窗、停泊窗这些界面如果实现呢如果用Appliction的方式会很麻烦,如果写成Eclipse插件则实现这些界面风格不会吹灰之力.
可以说把软件开发成Eclipse插件的最大好处就是界面风格友好统一,如果用户较熟悉Eclipse操作的话这种优势就更明显.
当然将软件写成插件形式也有一定的缺陷.
首先插件必须依附Eclipse,如果要安装插件就得先安装Eclipse.
其次,插件和Eclipse融合在一起,原Eclipse的一些菜单和工具栏是无法完全屏蔽的.
5.
2插件的HelloWorld5.
2.
1使用向导一步步创建HelloWorld我们利用Eclipse的"新建"向导来创建一个简单的插件.
1、新建一个插件项目(1)选择主菜单"文件→新建→项目",在弹出的窗口中(如图5.
1所示)选择"插件开发"下的"插件项目",然后单击"下一步".
图5.
1项目类型选择(2)如图5.
2所示,输入项目名"myplugin",其他设置不变,然后单击"下一步".
图5.
2项目名称(3)在新显示的窗口中接受所有缺省值不变,直接单击"下一步",这时将显示模板选择窗口(如图5.
3所示).
勾选"使用其中一个模板来创建插件"项,然后选择模板"Hello,World"项.
最后单击"完成"结束向导对话框.

图5.
3模板选择窗口2、插件项目myplugin简介如果在新建项目中操作正确,Eclipse将显示如图5.
4所示界面.
图5.
4建立一个插件项目后的Eclipse界面界面的左边视图中多了一个名为"myplugin"的项目.
项目中有两个文件:MypluginPlugin.
java、SampleAction.
java.
MypluginPlugin.
java较重要,今后将会使用到它,而SampleAction.
java则是一个类似JFace中的Action,可以把它看做是插件中的Action,等会运行时我们将看到SampleAction.
java的效果.
项目根目录下还有一个非常重要文件的plugin.
xml,这个文件是插件的入口文件,Eclipse是根据这个文件里的设置信息来加载插件的.
在插件开发初期会频繁在这个文件中做编辑,术语叫"设置扩展点".
象在Eclipse的增加主菜单、视图、按钮等,都是在这个文件里面设置不同的扩展点,后面的将详细讲到如何编辑此文件.
有人会问:开发一个系统会有很多的菜单和按钮,是不是都要在这个文件里设置呢回答:不必.
在plugin.
xml里只设置和Eclipse接壤的主要扩展点,其他软件自有的菜单和按钮不用在plugin.
xml设置了.
图5.
4的Eclipse界面中部显示的就是plugin.
xml的设置窗口,单击该窗口下部的plugin.
xml项后(如图5.
5所示),就可以直接编辑此文件.
图5.
5plugin.
xml编辑窗下部的选项条3、运行插件如图5.
6所示,选择主菜单"运行→运行方式→运行工作平台",这种是专用是插件的运行方式,它将打开一个新的Eclipse环境,并同时将插件项目编译加载到新的Eclipse环境中.
今后开发经常要通过这个方法来试运行所开发的插件项目,不过那时候选择"运行→调试方式→运行工作平台"以调试方式来运行插件会比较多,Eclipse支持调试期间的热修改,不用每次修改都新启一个Eclipse,这样能节省很多调试开发时间.
新开的Eclipse界面如图5.
6所示,在新的Eclipse环境中新增加了一个工具栏按钮和一个主菜单项.
单击此按钮或菜单项,将弹出一个"Hello,Eclipseworld"信息提示框.
图5.
6myplugin插件运行效果图4、总结本节里我们还只是依样画葫芦,感觉有点云里雾里的吧.
但不管怎么样,第一个Eclipse插件已经在我们手里诞生了,下一节我们将不用HelloWorld模板来新建一个空白的插件项目,然后一步步的经过手工实现这个HelloWorld插件项目所拥有的功能.
5.
2.
2以空白项目为基础手工创建HelloWorld1、新建项目按照上一节所讲新建插件项目的方法,新建一个名为myplugin2的插件项目.
注意在最后一步不要选择任何模板,直接单击"完成"结束向导对话框,除此之外的其他步骤都一样.
很幸运,Eclipse3.
0修正了很多BUG,象以前用Eclipse2.
X中文版时,在这一步还会出很多库引用的错误,要很麻烦的一个个去修正.
2、创建IWorkbenchWindowActionDelegate接口的实现类新建一个包book.
chapter_5,并将上一节中由HelloWorld模板生成的myplugin项目中的SampleAction.
java文件复制到本项目中(Eclipse支持鼠标拖拉操做).
然后对SampleAction做了一些小修改:删除了无用的注释和构造函数,修改了一下弹出框的提示文字,修改后的代码如下:/***本类相当于插件的Action,要在Eclipse中增加主菜单或工具栏按钮,*就需要写一个实现IWorkbenchWindowActionDelegate接口的类*/publicclassSampleActionimplementsIWorkbenchWindowActionDelegate{privateIWorkbenchWindowwindow;publicvoidrun(IActionaction){//打开一个信息提示框MessageDialog.
openInformation(window.
getShell(),"Myplugin2插件","Hello,这是手工做的插件");}publicvoidselectionChanged(IActionaction,ISelectionselection){}publicvoiddispose(){}publicvoidinit(IWorkbenchWindowwindow){this.
window=window;}}3、原plugin.
xml文件各设置项说明如图5.
7所示,将plugin.
xml文件打开,并单击窗口下的"plugin.
xml"项转到其代码编辑窗.
图5.
7plugin.
xml的代码编辑窗项详细介绍其中的各项设置如下:(1)项说明:是plugin.
xml的主体.
zid-插件的唯一标识.
实际项目中一般加上包名或网址名来命名id,比如eclipse的tomcat插件是这样命名的:org.
eclipse.
tomcat,这样在世界上就不会有插件的标识名和你重名了.
以后在某些扩展点中的属性也会用到标识符作为名称的前缀.
zname-插件的名称,可以不唯一.
zversion-插件版本号.
zprovider-name-插件开发商的名称,可以写上作者或公司的名称.
zclass-插件类的名称,即插件项目自动生成的MypluginPlugin2.
java文件的类,前面加上包名.
(2)项说明:这里是声明插件运行时需要的jar包,比如插件要连接MySQL数据库需要它的一个包,如下定义,其中"lib"是该包所在路径.
其中本插件自身的jar包也要声明,而且本插件在打包时将以myplugin2.
jar为名打包.
(3)项说明:在requires域中定义了该插件所要使用的依赖插件.
现在两项就够了,随着开发的不断深入这里将会添加更多对其它插件的引用.
如下是笔者的实际项目中的requires设置,它要用到draw2d和gef插件来画图、用于插件的帮助系统来创建建自己的帮助文档.
4、为HelloWorld修改plugin.
xml将如下代码加入到plugin.
xml的""行之后:说明:在项设置要扩展的扩展点,它是非常重要的一项.
zpoint="org.
eclipse.
ui.
actionSets",设置了本插件的扩展点为何,actionSets是指Eclipse的菜单、菜单项和工具栏按钮的扩展点z项表示一个action组(菜单、按钮).
label是显示的名称.
id其唯一标识符,只要保证在本plugin.
xml文件中不存在重复的id就行了.
visible指设置的按钮或菜单是否显示,如果设置成false,则不显示.
注意:要看visible设置的效果要将"透视图"关掉再重新打开.
z是下的子项,它表示在Eclipse中插入显示一个名为"样本菜单(M)"的主菜单.
separator标签是一个结束符,它可以对菜单分组.
z也是下的子项,由它设置菜单、按钮.
icon是图片的路径,如果该图片不存,默认是一个红色实心小框(Eclipse2.
X)或不显示图片而显示文字(Eclipse3.
X).
Class是按钮所对应的类,注意包名也要加上.
menubarPath表示把这个action做成一个菜单项放在上前定义的主菜单下.
toolbarPath表示把这个action再做成一个工具栏按钮.
id是标识符,设置成和class项一样的名称是个不错的选择.
以上仅是Eclipse的扩展点中的一种,此外还有其它的扩展点共有一百多种之多.
我们没有必要了解所有扩展点的设置,只须熟悉一些常用的扩展点即可,如视图的扩展点org.
eclipse.
ui.
views、编辑器的扩展点org.
eclipse.
ui.
editors等,本书将陆续给于介绍.
另外,各种扩展点在Eclipse的帮助中有详细的说明,其位置为:选择主菜单"帮助→帮助内容",然后打开"平台插件开发指南→参考→扩展点参考"项.
5、运行插件按上一节(5.
2.
1节)所说的方法运行插件(运行之前不妨将上节所建的myplugin项目关闭掉,关闭方法:右键单击myplugin项目名,然后在弹出菜单中选择"关闭项目").
myplugin2插件的效果如图5.
8所示图5.
8myplugin2插件运行效果图5.
3常用插件扩展点实战(plugin.
xml)在上一节(5.
2.
2节)已经对原有的plugin.
xml做了很详尽的介绍,plugin.
xml是插件和Eclipse的接口,Eclipse就象一所大宅子,它的外墙(plugin.
xml)有很多的门(扩展点),我们要熟练进出这座大宅子,先得搞清楚它有哪些门,当然我们只需要熟悉一些主要的门就足够应付90%的需求了.
本节将以开发需求为导向来介绍这些扩展点,并且本节所有实例都在5.
2.
2节所建立的myplugin2项目的基础上来进行讲解演示.
5.
3.
1加入透视图(perspectives)往开发一个插件,最常用的方式就是新增一个属于本插件专有的透视图,然后在此透视图基础上来展开软件开发,本书即采用这种方式.
1、准备工作我们先将以前用到的那些图标的icons目录复制一份到myplugin2项目中,复制后的路径如图5.
9所示:图5.
9图标的路径2、修改plugin.
xml文件,设置透视图的扩展点打开plugin.
xml文件的编辑框,将如下代码块插入到最后一行的之前:说明:zorg.
eclipse.
ui.
perspectives是透视图的扩展点zname-透视图的名称zicon-透视图的图标zclass-透视图所对应的类(我们还没编写,下一步将完成此类)zid-透视图标识,建议设置成和class一样的名称,省得以后扩展点设置得太多,搞得人糊涂.
3、建立透视图类在上一步的plugin.
xml中提前设置了透视图对应的类book.
chapter_5.
SamplePerspective,这一步我们就来在包book.
chapter_5中创建此类.
透视图的类必须实现IPerspectiveFactory接口,此接口只有一个方法createInitialLayout,我们让它先空实现好了.
SamplePerspective代码如下:文件名:SamplePerspective.
java-publicclassSamplePerspectiveimplementsIPerspectiveFactory{publicvoidcreateInitialLayout(IPageLayoutlayout){}}4、运行插件按以前所说的方法运行插件后,在新开的Eclipse环境中选择主菜单"窗口→打开透视图→其它".
在弹出如图5.
10的透视图选择窗口中,我们可以看到一个名为"myplugin透视图"的项.
图5.
10选择透视图选择并打开"myplugin透视图"项后,显示如图5.
11的Eclipse界面.
我们发现该透视图光秃秃的什么也没有.
没关系,我们下一小节就会往这个透视图加入两个视图.
图5.
10myplugin透视图的效果图5、总结由本小节可以看到在Eclipse创建一个界面(菜单、按钮、透视图)是多么的简单,我们都不用编写实际界面的创建代码,只要设置一些扩展点就行了.
第6章SWT概述在这一章里将把SWT和AWT/SWING做了简单的比较,并以一个HelloWorld的Java应用程序(Application)作为起步,让读者可以快速建立对SWT/JFace的感性认识.
在这一章里所有的例子都是以Java应用程序方式来写的,之所以如此,是因为Java应用程序代码简洁,且可以独立运行,便于讲解和示范.
当然,这些例子的代码方法同样适用于Eclipse的插件开发,SWT/JFace在Java应用程序和Eclipse插件开发中的使用是没有太多区别的.
6.
1SWT简介2003年,笔者对SWT/JFace(英文全称:StandardWidgetToolkit)还是仅有耳闻,知道在AWT/Swing之外,又有了一个新的图形API包,听说还很不错,当时书店里根本没有相关资料,只能在网上找到一些零星的文章来了解.
2004年前,笔者还极少用Java来写GUI程序(GUI全称:GraphicalUserInterfaces,图形用户界面),主要的工作都是用JSP来写网页.
用JAVA来开发大型的GUI程序实在很困难的事,大都丑陋又笨重(慢),SUN在GUI方向上的失败是公认的事实.
失败关键之处在于Java的图形API包AWT/SWING在速度和外观上都不能让人满意,外观总是和同操作系统平台下的其他软件格格不入,对机器配置的需求也似乎永无止境.
2004年初,笔者有幸参与到一个用Eclipse插件方式来开发的软件项目中,该软件使用到了SWT/JFace,那界面实在是太酷太漂亮了,让人为之耳目一新,而且界面响应速度极快,这真的是用Java开发的吗当时竟然有点不敢相信.
无疑,SWT/JFace象一股清新的风吹入了Java的GUI开发领域,为这个沉闷的领域带来了勃勃生机.
虽然SUN不接纳SWT/JFace作为Java中的一种图形API标准,但它虽然借着Eclipse的优异表现,以不可阻挡之势向前发展着.
终于可以用SWT轻松的开发出高效率的GUI程序,且拥有标准的Windows外观,Eclipse软件就是基于SWT/JFace构建的,大家看看Eclipse3.
0就知道SWT有多么的棒.
图6.
1SWT、JFace、GUI程序三者关系示意图如上图6.
1,为了方便开发SWT程序,在SWT基础上又创建了一个更易用、功能强大的图形包"JFace".
然而,JFace并不能完全覆盖SWT的所有功能,所以编程时SWT、JFace都会要用到,但是一般来说,能用JFace的组件就最好不要用SWT的.
6.
2SWT中的包SWT是Eclipse图形API的基础,本节将简单介绍一下SWT中所包含的子包.
1、org.
eclipse.
swt.
widgets最常用的组件基本都在此包中,如Button、Text、Label、Combo等.
其中两个最重要的组件当数Shell和Composite:Shell相当于应用程序的主窗口;Composite相当于SWING中的Panel对象,是容纳组件的容器.
2、org.
eclipse.
swt.
layout主要的界面布局方式在此包中.
SWT对组件的布局也采用了AWT/SWING中的Layout和LayoutData结合的方式.
3、org.
eclipse.
swt.
custom对一些基本图形组件的扩展在此包中,比如其中的CLabel就是对标准Label组件的扩展,在CLabel上可以同时加入文字和图片.
在此包中还有一个新的布局方式StackLayout.
4、org.
eclipse.
swt.
eventSWT采用了和AWT/SWING一样的事件模型,在包中可以找到事件监听类和相应的事件对象.
比如,鼠标事件监听器MouseListener,MouseMoveListener等,及对应的事件对象MouseEvent.
5、org.
eclipse.
swt.
graphics此包中包含针对图片、光标、字体或绘图API.
比如,可通过Image类调用系统中不同类型的图片文件.
6、org.
eclipse.
swt.
ole.
win32对不同平台,SWT有一些针对性的API.
例如,在Windows平台,可以通过此包很容易的调用OLE组件,这使得SWT程序也可以内嵌IE浏览器或Word、Excel等程序.
此外还有org.
eclipse.
swt.
dnd、org.
eclipse.
swt.
printing、org.
eclipse.
swt.
program、org.
eclipse.
swt.
accessibility、org.
eclipse.
swt.
browser、org.
eclipse.
swt.
awt等包,在此不一一介绍了.
这些包一般很少用到,只需要稍微了解一下就行了,不必深究.
6.
3用SWTDesigner写一个HelloWorldSWTDesigner是优秀的SWT/JFace开发辅助工具,本书大都SWT/JFace的例子都是使用它来生成代码后,再进行修改而成.
当然,SWTDesigner并非是阅读和运行这些例子的必须条件.
本节将用SWTDesigner来写出第一个基于SWT的HelloWorld程序,以此给读者演示在开发中是如何使用SWTDesigner的.
6.
3.
1使用用向导建立一个SWT/JFaceJava项目(1)选择主菜单"文件→新建→项目",弹出如下图6.
2所示窗口.
图6.
2新建项目窗口(2)选择"Designer"下的"SWT/JFaceJavaProject"项,单击"下一步",弹出如下图6.
3所示窗口.
图6.
3创建Java项目窗口(3)填写项目名称"myswt",项目布局选择第二个,单击"完成".
这时如果打开"java"透视图,可以看到多了一个名为"myswt"的项目,下方还排列着很多库引用,如下图6.
4所示窗口.
图6.
4"java"透视图注:(1)其实写SWT程序也不是一定要重新建立这样一个新的项目,原来老的"myproject"项目依然可以继续使用的,但必须将SWT、JFace包及一些相关的包引用到Java构建路径中,手工一步步做这个工作太过于繁锁.
有一个简单的方法:借助SWTDesigner新建项目时保存在.
classpath文件中的库引用,将其复制粘贴到myproject的.
classpath中即可.
(2)当编写Java程序时,笔者认为"Java"透视图要比默认的"资源"透视图好用,主要是因为前者的包显示不是树状的,用起来较方便.
但选择哪一种透视图,还是要看各人的习惯和喜好.
本书以后的所讲内容将统一使用"Java"透视图.
6.
3.
2导入SWT的原生库想要运行Java应用程序,必须将SWT的原生包导入到项目中,否则该项目在运行程序时会报异常"java.
lang.
UnsatisfiedLinkError:noswt-win32-3063injava.
library.
path",并弹出图6.
5所示的错误提示框.
图6.
5未导入SWT原生包时产生的错误提示框导入SWT原生包的步骤如下:(1)右键单击项目名"myswt",在弹出菜单中选择"导入",则会弹出如图6.
6所示窗口.
图6.
6导入窗口(2)选择"文件系统"后单击"下一步",转到如图6.
7所示窗口图6.
7选择导入文件(3)通过"浏览"按钮找到SWT原生库的路径(也可以直接输入路径文字),路径为"C:eclipsepluginsorg.
eclipse.
swt.
win32_3.
0.
1oswin32x86".
然后将"swt-win32-3063.
dll"选上,单击"完成",导入SWT原生包的设置结束.
6.
3.
3新建一个SWT类文件参阅"4.
2节创建Java项目并运行"所讲方法,新建一个类文件.
(1)在"Java"透视图的"包资源管理器"中,右键单击"com.
swtdesigner"包,在弹出菜单中选择"新建→其他",弹出如图6.
8所示窗口.
图6.
8选择新建的类型(2)选择"Designer→SWT→ApplicationWindow",单击"下一步",弹出如图6.
9所示窗口.
图6.
9类文件的设置(3)类的名称填"HelloWorld",并选择"Createcontentsin(类代码的生成方式)"为第三项"publicstaticmain()method"(第三项生成的代码结构最简单),弹击"完成".
Eclipse将自动生成HelloWorld.
java的代码,代码如下(注释为笔者手工加入):packagecom.
swtdesigner;//包名importorg.
eclipse.
swt.
widgets.
Display;//程序所用到的类都会用import标记在这里,importorg.
eclipse.
swt.
widgets.
Shell;//import的快捷键Ctrl+Shift+OpublicclassHelloWorld{//一个标准的Java类HelloWorldpublicstaticvoidmain(String[]args){//display负责管理事件循环和控制UI线程和其他线程之间的通讯.
finalDisplaydisplay=Display.
getDefault();finalShellshell=newShell();//shell是程序的主窗口shell.
setSize(327,253);//设置主窗口的大小shell.
setText("SWTApplication");//设置主窗口的标题shell.
layout();//shell应用界面布置shell.
open();//打开shell主窗口while(!
shell.
isDisposed()){//如果主窗口没有关闭,则一直循环if(!
display.
readAndDispatch())//如果display不忙display.
sleep();//display休眠}}}从这个代码可以看到,创建一个典型的SWT应用程序需要以下步骤:z创建一个Displayz创建一个或多个Shellz设置Shell的布局(3.
5节将讲到布局的内容)z创建Shell中的的组件(注:本例还没有加入组件,只是一个空窗口)z用open()方法打开Shell窗口z写一个事件转发循环z销毁display6.
3.
4在主窗口加入一个文本框组件如果运行HelloWorld.
java,它还仅是一个空荡荡的主窗口.
我们利用SWTDesigner将一个SWT的文本框组件加入到主窗口中,操作步骤如图6.
10所示.
图6.
10将文本框加入到主窗口的操作示意图图中所示的操作步骤用文字描述如下:(1)先将编辑器最大化.
然后单击Eclipse的左下角的"Design"选项页,则编辑器由代码视图变成设计视图.
(2)选择SWT组件栏中"SWTControls"分类下的"Text"组件,然后在主窗口上单击,将Text框放入.
注意这里不是通常的将组件拖入到窗口.
(3)转到属性窗口,在"text"项里填写"HelloWorld".
单击Eclipse左下角的"Source"返回到编辑器的代码视图,代码如下:packagecom.
swtdesigner;importorg.
eclipse.
swt.
widgets.
Display;importorg.
eclipse.
swt.
widgets.
Shell;importorg.
eclipse.
swt.
SWT;importorg.
eclipse.
swt.
widgets.
Text;publicclassHelloWorld{publicstaticvoidmain(String[]args){finalDisplaydisplay=Display.
getDefault();finalShellshell=newShell();shell.
setSize(327,253);shell.
setText("SWTApplication");新插入的界面核心代码Texttext=newText(shell,SWT.
BORDER);//新建一个text对象text.
setText("HelloWorld");//给text文本框设置初始文字HelloWorldtext.
setBounds(88,94,100,25);//设置文本框的位置和大小,(x轴坐标,y轴坐标,宽度,高度)END-shell.
layout();shell.
open();while(!
shell.
isDisposed()){if(!
display.
readAndDispatch())display.
sleep();}}}6.
3.
5运行HelloWorld.
java选择主菜单"运行→运行方式→Java应用程序",运行界面如图6.
11所示:图6.
11HelloWorld的第一次运行界面以上的程序例子还是比较简单的,如图6.
12所示,给出一个稍微标准些的界面,并给出了各类和界面之间的对应关系.
注:在SWT中check框(复选框)也是一种Button.
图6.
12界面和类之间的对应关系图其中Display和Shell的谱系图如图6.
13所示,Group和Button在3.
3节有介绍.
图6.
13Display和Shell的谱系图6.
4关于SWT/JFace例程的说明由于SWT/JFace应用程序例子的整体代码结构都基本一样,如下:packagecom.
swtdesigner;importorg.
eclipse.
swt.
widgets.
Display;importorg.
eclipse.
swt.
widgets.
Shell;importorg.
eclipse.
swt.
SWT;importorg.
eclipse.
swt.
widgets.
Text;publicclassHelloWorld{publicstaticvoidmain(String[]args){finalDisplaydisplay=Display.
getDefault();finalShellshell=newShell();shell.
setSize(327,253);shell.
setText("SWTApplication");新插入的界面核心代码-…………END-shell.
layout();shell.
open();while(!
shell.
isDisposed()){if(!
display.
readAndDispatch())display.
sleep();}}}为了节省篇幅,以后的例子一般都会省略上面代码框架前后部份,只给出中间省略号处的核心代码,要想得到完整的代码请查阅本书随书光盘中的例程.
6.
5实践建议SWTDesigner还无法完成所有的界面设计工作,所以在界面开发中依然是以手工写代码为主,而且手写代码某些时候比界面拖拉操作更快捷.
以下是笔者在使用SWTDesigner开发界面时的基本流程:z新开一个临时的Application文件,用SWTDesiger快速做好开发所需要的部份界面.
z将自动生成的代码移植到正式项目中,进行手工修改和代码精简.
另外,由于SWTDesigner不是很稳定,所以在使用时还应注意:z不要在界面中加入太多组件.
z不要频繁的移动组件,或者删除又添加组件,否则很可能因为内存耗尽而死机.
6.
6本章小结本章主要介绍了SWT的一些基本知识,并且用SWTDesigner开发出了本书的第一个SWT程序.
通过这章的学习,读者对SWT有一个初步的认识,并了解到了如何用SWTDesigner来开发SWT程序.
第7章SWT/JFace的事件模型7.
1事件的四种写法SWT的事件模型是和Java标准的AWT基本一样的.
在第6章的例子中,如何来实现文本框的事件响应呢比如:鼠标双击文本框弹出一个对话框.
下面将按照事件的四种写法来实现它.
7.
1.
1匿名内部类写法在原来的代码行"text=newText(shell,SWT.
BORDER);"之下插入如下语句://addMouseListener加入鼠标事件的监听器text.
addMouseListener(newMouseAdapter(){publicvoidmouseDoubleClick(MouseEvente){//鼠标双击事件的方法//打开一个信息框MessageDialog.
openInformation(null,"","HelloWorld");}});newMouseAdapter()就是一个匿名内部类.
我们建立了一个继承于MouseAdapter的类,但并没有给这个类命名,并且没有用通常的写法,而是直接在text.
addMouseListener方法中写下了类的代码,这就是所谓的匿名内部类(更详尽的解释请参阅Java基础类书籍).
使用匿名内部类来写事件代码简单方便,但也要注意它的一些缺点:z由于事件处理代码会随着组件一起分散在代码中的各个部份,不够集中,这样会导致代码阅读与维护上的不便.
z各事件的处理全部由嵌套的程序块组成,视觉上会显示有些乱.
如果事件处理代码很长,也会导致了阅读与维护上的不便.
z当工具栏、菜单栏目等也需要处理相同的用户行为时,无法重用事件中的处理代码,导致了代码的臃肿.
7.
1.
2命名内部类写法事件代码使用命名内部类的方式,可以解决匿名内部类存在的问题:首先,事件处理代码都集中在一起,并且都具有有意义的名称,程序容易阅读与维护;另外,单个的事件处理程序也可以被工具栏、菜单栏等重用.
实现代码如下:publicclassHelloWorld{publicstaticvoidmain(String[]args){……Texttext=newText(shell,SWT.
BORDER);//加入鼠标事件监听器,并用下面代码所定义的内部类生成一个对象text.
addMouseListener(newMyMouseDoubleClick());……}//定义一个名为MyMouseDoubleClick的内部类privatestaticfinalclassMyMouseDoubleClickextendsMouseAdapter{publicvoidmouseDoubleClick(MouseEvente){MessageDialog.
openInformation(null,"","HelloWorld");}}}7.
1.
3外部类写法这种写法和命名内部类有些相似,只不过是将MyMouseDoubleClick类从HelloWorld.
java中拿出去,单独写成一个类文件.
这种写法有和命名内部类一样的优点,但因为要单独写成一个文件,写起来会麻烦一些.
实现代码如下//文件1:HelloWorld.
javapublicclassHelloWorld{publicstaticvoidmain(String[]args){……Texttext=newText(shell,SWT.
BORDER);//加入鼠标事件监听器,并用下面代码所定义的内部类生成一个对象text.
addMouseListener(newMyMouseDoubleClick());……}}//文件2:MyMouseDoubleClick.
javapublicclassMyMouseDoubleClickextendsMouseAdapter{publicvoidmouseDoubleClick(MouseEvente){MessageDialog.
openInformation(null,"","HelloWorld");}}7.
1.
4实现监听接口的写法将HelloWorld类实现MouseListener接口,这样类本身就成了一个监听器,使得加入监听器的代码可以更简洁.
这种方式适合加入监听器的组件较多,且要求监听器的事件处理代码可以被组件共用.
这种方式还有一个要注意的地方:事件方法和其他方法混合在了一起,容易引起误读,所以应该在事件方法前加入详细的注释说明.
实现MouseListener接口要写的事件方法多一些,当然没用的事件方法可以空实现.
如果继承MouseListener接口的适配器MouseAdapter,则只写需要的方法就行了.
另外要注意:只有接口才能有多继承的特性,所以如果HelloWorld已经是某个类的子类,就只能用实现接口的方式,而不能继承接口的适配器了.
给出示例代码如下:publicclassHelloWorldextendsMouseAdapter{//或implementsMouseListenerpublicstaticvoidmain(String[]args){……Texttext1=newText(shell,SWT.
BORDER);Texttext2=newText(shell,SWT.
BORDER);text1.
addMouseListener(this);text2.
addMouseListener(this);……}publicvoidmouseDoubleClick(MouseEvente){MessageDialog.
openInformation(null,"","HelloWorld");}}7.
1.
5总结匿名内部类方式在写起来方便些,但不适合事件代码太长太多的情况.
从代码书写、阅读、维护以及程序的可扩展性角度来看,命名内部类写法最为值得推荐.
外部类的写法主要是为了代码重用才考虑使用,如果包(package)外的类要用到此事件处理代码,这时外部类就派上用场了.
而第四种写法,要求组件都可以共用事件代码时才能使用.
7.
2常用事件介绍除了上例中用于响应鼠标事件的addMouseListener,Eclipse还有一些常用的监听器,它们在各组件中的使用方法相同(如果该组件支持此种事件的话).
在此将它们简单介绍如下:zaddSelectionListener:这个监听器最最常用.
a)widgetSelected方法:当组件被选择(鼠标单击、按回车键)时触发此方法的事件处理程序.
b)widgetDefaultSelected方法:用于某些很少触发选择事件的组件,所以这个方法在实际开发中也很少用.
比如,文本框回车事件、列表框双击事件等,就只能用widgetDefaultSelected方法,用widgetSelected方法无效.
zaddKeyListener(按键)a)keyPressed方法:当前焦点停在组件时,按下键盘任一键时触发.
但对于某些组件(如按钮Button)按回车键无法执行此方法.
b)keyReleased方法:按键弹起时触发.
zaddFocusListener(焦点)a)focusGained方法:得到焦点时触发.
b)focusLost方法:失去焦点时触发zaddMouseListener(鼠标)a)mouseDown方法:鼠标按下时触发b)mouseUp方法:鼠标放开时触发c)mouseDoubleClick方法:鼠标双击时触发以上几个就是常用的事件了,很少吧,SWT的事件模型还是极容易掌握的.
事实上除了addSelectionListener较常用之外,其他基本都很少用到.
7.
3在事件代码中如何访问类中的变量7.
3.
1访问类中的变量的三种方法在写事件代码的时候,常常需要引用主类中的变量,要访问这些变量是需要一些技巧的.
方法一:加final修饰符.
publicclassHelloWorld{publicstaticvoidmain(String[]args){……//将变量前加final,否则在事件代码里不能引用finalStringstr="陈刚";text.
addMouseListener(newMouseAdapter(){publicvoidmouseDoubleClick(MouseEvente){System.
out.
println(str);//str变量前要加final}});……}}方法二:将变量str变成类的实例变量.
但这种方法扩大了str变量的有效范围.
publicclassHelloWorld{//由于引用它的代码是在静态方法内才加static,否则不必要static.
staticStringstr="陈刚";publicstaticvoidmain(String[]args){……}}方法三:将事件代码写成命名内部类,然后通过构造函数的参数来传入.
这种方法较繁琐一些.
publicclassHelloWorld{publicstaticvoidmain(String[]args){Stringstr="陈刚";//通过构造函数参数将str值传入text.
addMouseListener(newMyMouseDoubleClick(str));}//匿名内部类MyMouseDoubleClickprivatestaticfinalclassMyMouseDoubleClickextendsMouseAdapter{privateStringstring;//建一变量引用str的值publicMyMouseDoubleClick(Stringstr){//通过构造函数参数接受str值this.
string=str;}publicvoidmouseDoubleClick(MouseEvente){System.
out.
println(string);}}}7.
3.
2Java中变量的称法和说明此节中用到了一些Java变量方面的知识,在此一并附上.
Java中有三种容易混淆的变量:局部变量、实例变量、类变量,如下程序所示:publicclassVariable{staticintallClicks=0;//类变量Stringstr="广西桂林";//实例变量publicvoidmethod(){inti=0;//局部变量}}类变量的定义前加有static,这表示它是一个静态的,因此类的多个实例共用一个类变量.
实例变量定义在类的方法之外,一般处于类的起始位置,类的每一个实例都独自拥有一份实例变量的拷贝.
局部变量的有效范围在程序块中,它的生命期仅限于此程序块内.
实例变量在有些书籍中也翻译成"域"或"成员变量".
在面向数据库的实体类(Hibernate中也称POJO-简单原始的Java对象)中,被称之为"属性"或"字段"的变量,也是实例变量的一种.
使用变量的一般原则是,尽量使变量的有效范围最小化:优先考虑用局部变量,其次是实例变量,最后才是类变量.
另外,还有一种常量的写法,它比类变量写法仅多了个final,如下所示:finalstaticintALL_CLICKS=0;//常量注意ALL_CLICKS是全大写的,这是常量的规范命名方式.
这时ALL_CLICKS被final约束,它不能再被赋值了.
7.
4本章小结本章主要介绍了事件的四种写法,及事件访问类中变量的方法,这些知识在SWT编程中经常要用到.
但是,读者可以不必太执着于本章的内容,可以快速浏览后,进入下一章的学习,当用到时,再回过头来查阅.
第18章常用插件扩展点在第17章对plugin.
xml作了少量介绍,plugin.
xml是插件和Eclipse内核的接口,Eclipse就像一所大宅子,它的外墙(plugin.
xml)有很多的门(扩展点),要熟练进出这座大宅子,先得搞清楚它有哪些门(扩展点).
插件的扩展点非常之多,但很多扩展点都不常用到,只要熟悉一些主要的扩展点即可.
本节将面向实际开发需要来介绍这些扩展点,并且本章所有实例都在第17章建立的myplugin2插件项目的基础上创建.
18.
1加入透视图(perspectives)开发一个插件,最常用的方式就是新增一个属于本插件专有的透视图,然后在此透视图基础上来展开功能,本书也采用这种方式.
18.
1.
1准备工作先将以前用到的包括图标的icons目录复制一份到myplugin2项目中,复制后的路径如图18.
1所示.
图18.
1图标的路径18.
1.
2修改plugin.
xml文件,设置透视图的扩展点打开plugin.
xml文件的编辑框,将如下代码块插入到最后一行的项之前:代码说明:org.
eclipse.
ui.
perspectives是透视图的扩展点.
name:透视图的名称.
icon:透视图的图标.
class:透视图所对应的类(还没编写,下一步将完成此类).
id:透视图标识,建议设置成和class一样的名称,省得以后扩展点设置得太多,让人糊涂.
18.
1.
3建立透视图类在18.
1.
2小节的plugin.
xml中提前设置了透视图对应的类cn.
com.
chengang.
SamplePerspective,这一步就在包cn.
com.
chengang中创建此类.
透视图类必须实现IperspectiveFactory接口,此接口只有一种方法createInitialLayout,先让它空实现.
SamplePerspective类的代码如下:文件名:SamplePerspective.
java-publicclassSamplePerspectiveimplementsIPerspectiveFactory{publicvoidcreateInitialLayout(IPageLayoutlayout){}}18.
1.
4运行插件运行插件,然后在新Eclipse环境中选择主菜单"窗口→打开透视图→其他"选项.
在弹出窗口中,可以看到一个名为myplugin透视图的项,如图18.
2所示.
选择并打开"myplugin透视图"选项后,显示如图18.
3所示的Eclipse界面.
我们发现该透视图光秃秃的什么也没有.
没关系,下面就会向这个透视图中加入两个视图.
图18.
2选择透视图图18.
3myplugin透视图的效果图18.
1.
5总结由本节可以看到,在Eclipse插件环境中,创建一个菜单、按钮、透视图界面是多么简单,都不用编写实际界面的创建代码,只要设置一些扩展点就行了.
18.
2在透视图中加入视图(views)接着18.
1节的内容,给透视图加入两个视图,实现的步骤如下所述.
18.
2.
1修改plugin.
xml文件,设置视图的扩展点打开plugin.
xml文件的编辑框,将如下代码块插入到最后一行的之前:代码说明:org.
eclipse.
ui.
views是视图的扩展点.
…是视图的分组名及id标识,它的效果体现在"显示视图"窗口里,显示视图的打开方法是:在主菜单选择"窗口→显示视图→其他"选项,图18.
4中的左图是本例设置的效果.
项中的id属性要保证它在Eclipse的所有插件中惟一.
如果和Ant插件的id相同,原Ant组就会被myplugin2视图组抹掉了(右图).
如果删除掉不设置,则Eclipse会自动新增一个"其他"组,并将两视图加入(中图).
的category是表示本视图属于哪个组,与上面项的id值相同.
的class是视图所对应的类(还没编写,下一步将完成这两个类).
的id是视图标识,建议设置成和class一样的名称.
图18.
4显示视图窗口18.
2.
2创建视图类在18.
2.
1小节的plugin.
xml中提前设置了视图对应的类:cn.
com.
chengang.
View1、View2,本小节就来在包cn.
com.
chengang中创建这两个视图类.
视图的类必须继承抽象类ViewPart,此类有两种方法createPartControl、setFocus.
我们要在createPartControl方法创建两个视图的界面组件,第一个视图创建一个列表,第二个视图创建一个文本框.
而setFocus是关于视图焦点的方法,一般都不用写,让它空实现.
两类的代码如下:文件名:View1.
java-publicclassView1extendsViewPart{publicvoidcreatePartControl(Compositeparent){CompositetopComp=newComposite(parent,SWT.
NONE);topComp.
setLayout(newFillLayout());Listlist=newList(topComp,SWT.
BORDER);list.
add("中国");list.
add("美国");list.
add("法国");}publicvoidsetFocus(){}}文件名:View2.
java-publicclassView2extendsViewPart{publicvoidcreatePartControl(Compositeparent){CompositetopComp=newComposite(parent,SWT.
NONE);topComp.
setLayout(newFillLayout());Texttext=newText(topComp,SWT.
BORDER);text.
setText("我是text框");}publicvoidsetFocus(){}}18.
2.
3修改透视图类SamplePerspective在18.
1节加入一个透视图时,建立了一个透视图类SamplePerspective,当时有一个继承自接口的方法createInitialLayout,它还是空实现的.
本例将通过修改这种方法,将两个视图加入到透视图中.
createInitialLayout方法的代码如下://参数IPageLayout是用于透视图的布局publicvoidcreateInitialLayout(IPageLayoutlayout){//得本透视图的编辑空间标识StringeditorArea=layout.
getEditorArea();/**将视图1加入到透视图的左部*"left"视图区的id标识为"left"*IPageLayout.
LEFT在透视图布局中的位置靠左*0.
2f占用透视图20%的宽度*editorArea使用透视图的编辑空间*/IFolderLayoutleft=layout.
createFolder("left",IPageLayout.
LEFT,0.
2f,editorArea);left.
addView("cn.
com.
chengang.
View1");//参数为plugin.
xml中视图1的id标识//将视图2加入到透视图的底部IFolderLayoutbottom=layout.
createFolder("bottom",IPageLayout.
BOTTOM,0.
8f,editorArea);bottom.
addView("cn.
com.
chengang.
View2");/**将17.
2.
2小节第4点所定义的actionset(主菜单、工具栏按钮)加入到本透视图.
这个效果要在*plugin.
xml文件的action设置中将visible="false"才看得出效果,这时打*开其他透视图,action设置的主菜单、工具栏按钮将不会出现在界面上,只有打*开本透视图才会出现,因为本透视图用下面的语句手工加入了此action*参数myplugin2.
actionSet为action在plugin.
xml文件中设置的id标识*/layout.
addActionSet("myplugin2.
actionSet");}18.
2.
4运行插件运行插件后,打开myplugin透视图,效果如图18.
5所示.
如果两个视图还没有显示在透视图上,则需要把透视图先关闭,再打开,以应用新的透视图设置.
图18.
5加入两视图后的透视图18.
3在视图之间实现事件监听两个视图中的组件之间的互动,在开发插件时是经常碰到的问题.
例如,在18.
2.
4小节的界面中,单击视图1列表中的某项时,视图2的文本框也作相应显示.
本节将实现此功能.
18.
3.
1修改View1.
java、View2.
java首先,要在两视图中互动就必须先解决"如何在视图1中取得视图2的对象"的问题.
Eclipse通过plugin.
xml来加载插件和插件中的扩展点(如视图),所以可以由视图的id标识来取得视图对象,具体语句如下:IWorkbenchPagewbp=getViewSite().
getPage();IViewPartview2=wbp.
findView("cn.
com.
chengang.
View2");得到了视图2的对象后,其他一切就都好办了,先给出修改后View1如下:publicclassView1extendsViewPart{publicvoidcreatePartControl(Compositeparent){CompositetopComp=newComposite(parent,SWT.
NONE);topComp.
setLayout(newFillLayout());finalListlist=newList(topComp,SWT.
BORDER);list.
add("中国");list.
add("美国");list.
add("法国");//列表选择事件监听list.
addSelectionListener(newSelectionListener(){publicvoidwidgetSelected(SelectionEvente){//由IWorkbenchPage取出view2IWorkbenchPagewbp=getViewSite().
getPage();IViewPartview2=wbp.
findView("cn.
com.
chengang.
View2");//将当前选择的列表项显示在文本框中Texttext=((View2)view2).
getText();text.
setText(list.
getSelection()[0]);}publicvoidwidgetDefaultSelected(SelectionEvente){}});}publicvoidsetFocus(){}}然后将View2的文本框对象改成类的实例变量,并编写它相应的set/get方法,代码如下:publicclassView2extendsViewPart{privateTexttext;publicvoidcreatePartControl(Compositeparent){CompositetopComp=newComposite(parent,SWT.
NONE);topComp.
setLayout(newFillLayout());text=newText(topComp,SWT.
BORDER);text.
setText("我是text框");}publicvoidsetFocus(){}//文本框text相应的set/get方法publicTextgetText(){returntext;}publicvoidsetText(Texttext){this.
text=text;}}18.
3.
2总结(1)在插件中IWorkbenchPage对象比较重要,在这里再给出一种获得此对象的方法.
当不是在视图里而是在Action里要取IWorkbenchPage对象时,就可以用下面的方法:Myplugin2Plugin.
getDefault().
getWorkbench().
getActiveWorkbenchWindow().
getActivePage();(2)IWorkbenchPage.
findView("cn.
com.
chengang.
View2"),中的参数为"视图2"在plugin.
xml中设置的id标识,由此可见plugin.
xml文件在插件中的地位是极其重要的.
IWorkbenchPage除了findView方法之外,还有findEditor方法是用来得到编辑器的.
像"cn.
com.
chengang.
View2"这种标识符在系统开发中会经常用到,最好建立一个常量专用类来集中放置这些字符串常量,然后系统中用的时候只用其常量名就行了,否则把标识符的字串分散在代码中,以后改起来会让你痛不欲生.
常量类的示意代码如下:publicfinalclassStringConstants{publicfinalstaticStringVIEW1="cn.
com.
chengang.
View1";publicfinalstaticStringVIEW2="cn.
com.
chengang.
View2";}要用的时候则这样写:findView(StringConstants.
VIEW2);18.
4给视图加下拉菜单和按钮本例将给视图加入下拉菜单和按钮,如图18.
6所示.
同时再为列表添加一个右键菜单,这样读者可以用来和视图的下拉菜单进行比较阅读.
图18.
6效果图18.
4.
1创建ActionGroup类加入菜单和按钮的方法与SWT/JFace组件的一样.
先创建一个ActionGroup代码如下:文件名:MyActionGroup.
java-publicclassMyActionGroupextendsActionGroup{/**加入按钮*/publicvoidfillActionBars(IActionBarsactionBars){if(actionBars==null)return;IToolBarManagertoolBar=actionBars.
getToolBarManager();toolBar.
add(newAction1());toolBar.
add(newAction2());}/**加入下拉菜单、右键弹出菜单*/publicvoidfillContextMenu(IMenuManagermenu){if(menu==null)return;menu.
add(newAction1());menu.
add(newAction2());}privateclassAction1extendsAction{publicAction1(){ImageDescriptorimageDesc=WorkbenchImages.
getImageDescriptor(IworkbenchGraphicConstants.
IMG_ETOOL_HOME_NAV);setHoverImageDescriptor(imageDesc);setText("Action1");}publicvoidrun(){}}privateclassAction2extendsAction{publicAction2(){ImageDescriptorimageDesc=WorkbenchImages.
getImageDescriptor(IworkbenchGraphicConstants.
IMG_ETOOL_IMPORT_WIZ);setHoverImageDescriptor(imageDesc);setText("Action2");}publicvoidrun(){}}}程序说明:本程序中含有两个Action类:Action1、Action2,和以往的Action不同之处在于它的图像描述符是直接从Eclipse环境中取得.
既然插件在Eclipse环境内运行,那么Eclipse环境本身的图标就可以直接拿来使用.
fillContextMenu方法比起以前的少了几句.
在18.
4.
2小节,可以看到它移出到View1类中去了,主要原因是为了此方法兼顾添加视图的下拉菜单.
18.
4.
2修改View1类在View1中增加了三种方法,分别用来加入视图的导航栏按钮、下拉菜单,以及加入列表List的右键菜单.
代码如下:publicclassView1extendsViewPart{privateListlist;//将List写成类的实例变量,以扩大它的可访问范围publicvoidcreatePartControl(Compositeparent){CompositetopComp=newComposite(parent,SWT.
NONE);topComp.
setLayout(newFillLayout());list=newList(topComp,SWT.
BORDER);list.
add("中国");list.
add("美国");list.
add("法国");//列表选择事件监听(和以前一样,省略)/**加入导航栏按钮、下拉菜单、右键菜单*/MyActionGroupactionGroup=newMyActionGroup();fillViewAction(actionGroup);//加入视图的导航栏按钮fillViewMenu(actionGroup);//加入视图的下拉菜单fillListMenu(actionGroup);//加入视图的下拉菜单}/***加入视图的导航栏按钮*/privatevoidfillViewAction(MyActionGroupactionGroup){IActionBarsbars=getViewSite().
getActionBars();actionGroup.
fillActionBars(bars);}/***加入视图的下拉菜单*/privatevoidfillViewMenu(MyActionGroupactionGroup){IMenuManagermenu=getViewSite().
getActionBars().
getMenuManager();actionGroup.
fillContextMenu(menu);}/***加入列表List的右键菜单*/privatevoidfillListMenu(MyActionGroupactionGroup){MenuManagermenu1=newMenuManager();Menum=menu1.
createContextMenu(list);list.
setMenu(m);actionGroup.
fillContextMenu(menu1);}publicvoidsetFocus(){}}程序说明:过去写在ActionGroup中的两句移到了fillListMenu方法中.
视图加按钮、菜单的方式和以前SWT/JFace的方式是一样的.
只不过以前用自己生成MenuManager对象等,而现在的插件就只需要使用视图已有的MenuManager对象.
18.
5加入编辑器(editors)本节将给出如下的实例:双击视图1中的列表项,将在透视图中加入相应的编辑器.
这种效果就像在Eclipse中双击Java源文件,就会打开该源文件相对应的编辑器一样.
效果如图18.
7所示.
图18.
7编辑器效果图和以前一样,先来修改plugin.
xml文件将编辑器的扩展点加入,然后再创建相应的编辑器类,最后编写列表双击的事件代码.
18.
5.
1修改plugin.
xml文件,设置三个编辑器的扩展点代码说明:编辑器的扩展点是org.
eclipse.
ui.
editors,它各项的含义和视图扩展点基本一样,请参照18.
2.
1小节的视图扩展点的说明.
这里强调一点:icon也是必填项.
18.
5.
2创建三个编辑器类在18.
5.
1小节的plugin.
xml中,提前设置了编辑器对应的类cn.
com.
chengang.
ChinaEditor和UsaEditor、FranceEditor,本小节就来在包cn.
com.
chengang中创建这三个编辑器类.
编辑器必须实现IEditorPart接口,但通常是继承抽象类EditorPart类(EditorPart是IEditorPart的子类).
如果继承EditorPart则必须实现该抽象类的七种方法,在此先实现方法init、createPartControl.
本例只给出了ChinaEditor的代码,UsaEditor、FranceEditor与之完全类似,ChinaEditor的代码如下:文件名:ChinaEditor.
javapublicclassChinaEditorextendsEditorPart{/***Editor的初始化方法.
本方法前两句是固定不变的*/publicvoidinit(IEditorSitesite,IEditorInputinput)throwsPartInitException{System.
out.
println("init");setSite(site);setInput(input);//设置Editor标题栏的显示名称.
不要,则名称用plugin.
xml中的name属性//setPartName(input.
getName());//设置Editor标题栏的图标.
不要,则会自动使用一个默认的图标//setTitleImage(input.
getImageDescriptor().
createImage());}/***在此方法中创建Editor中的界面组件*/publicvoidcreatePartControl(Compositeparent){System.
out.
println("createPartControl");CompositetopComp=newComposite(parent,SWT.
NONE);topComp.
setLayout(newFillLayout());Texttext=newText(topComp,SWT.
BORDER);text.
setText("中国之编辑器");}//此五个抽象类的方法下面将讲解,现在让它空实现publicvoiddoSave(IProgressMonitormonitor){}publicbooleanisSaveAsAllowed(){returnfalse;}publicvoiddoSaveAs(){}publicbooleanisDirty(){returnfalse;}publicvoidsetFocus(){}}18.
5.
3创建IEditorInput获取视图对象是用IWorkbenchPage的findView方法,方法参数是视图在plugin.
xml中的id标识.
获取编辑器对象是用findEditor方法,但该方法的参数却不是id标识的字符串,而是一个IEditorInput对象.
另外,加载一个编辑器是用IWorkbenchPage的openEditor(editorInput,editorID)方法.
由上可知,编辑器都会要对应一个IEditorInput和一个EditorPart,而且在IWorkbenchPage中是根据IEditorInput来取得EditorPart,如图18.
8所示.
编辑器IEditorInputEditorPart图18.
8编辑器的组成在本小节将要创建三个Editor相对应的IEditorInput.
在这里只给出了ChinaEditor对应的IEditorInput,其他两个与之类似,请读者查阅配书光盘的代码.
文件名:ChinaEditorInput.
javapublicclassChinaEditorInputimplementsIEditorInput{/***返回true,则打开该编辑器后它会出现在Eclipse主菜单"文件"*最下部的最近打开的文档栏中.
返回false则不出现在其中*/publicbooleanexists(){returntrue;}/***编辑器标题栏的图标,不过它还需要在ChinaEditor中用*setTitleImage方法设置,才能出现在标题栏中*/publicImageDescriptorgetImageDescriptor(){returnWorkbenchImages.
getImageDescriptor(IWorkbenchGraphicConstants.
IMG_ETOOL_HOME_NAV);}/***编辑器标题栏的显示名称,和上面的getImageDescriptor*一样也要在ChinaEditor中用setPartName方法设置,才能出现在标题栏中*/publicStringgetName(){return"中国的编辑器";}/***编辑器标题栏的小黄条提示文字,不需像getName那样在ChinaEditor中再设置*/publicStringgetToolTipText(){return"这是视图1列表中的中国项对应的编辑器";}/***返回一个可以用做保存本编辑输入数据状态的对象,本例让它空实现*/publicIPersistableElementgetPersistable(){returnnull;}/***得到一个编辑器的适配器,本例让它空实现*IAdaptablea=newChinaEditorInput();*IFoox=(IFoo)a.
getAdapter(IFoo.
class);*if(x!
=null)*[用x来做IFoo的事情]*/publicObjectgetAdapter(Classadapter){returnnull;}}18.
5.
4打开编辑器有了EditorPart和IEditorInput后,就可以在Eclipse中打开编辑器了.
本例是要实现双击视图1的列表,则会打开列表项相对应的编辑器,因此在View1类的List对象添加一个鼠标双击事件监听器.
另外还要考虑到,如果已经打开了列表项对应的编辑器,则下次再双击时就不再打开该项的编辑器,而是将其设成当前选择的编辑器.
查找编辑器的方法是:IEditorParteditor=IWorkbenchPage.
findEditor(IEditorInput);打开编辑器的方法是:IWorkbenchPage.
openEditor(IEditorInput,editorID);所有代码如下:list.
addMouseListener(newMouseAdapter(){ChinaEditorInputchinaEditorInput=newChinaEditorInput();UsaEditorInputusaEditorInput=newUsaEditorInput();FranceEditorInputfranceEditorInput=newFranceEditorInput();publicvoidmouseDoubleClick(MouseEvente){/**根据列表不同项得到其相应的editorInput和editorID,其中*editorID指该编辑器在plugin.
xml文件中设置id标识值*/Listlist=(List)e.
getSource();//由MouseEvent得到列表对象StringlistStr=list.
getSelection()[0];//得到列表当前项字符IEditorInputeditorInput=null;StringeditorID=null;if(listStr.
equals("中国")){editorInput=chinaEditorInput;editorID="cn.
com.
chengang.
ChinaEditor";}elseif(listStr.
equals("美国")){editorInput=usaEditorInput;editorID="cn.
com.
chengang.
UsaEditor";}elseif(listStr.
equals("法国")){editorInput=franceEditorInput;editorID="cn.
com.
chengang.
FranceEditor";}//如果editorInput或editorID为空则中断返回if(editorInput==null||editorID==null)return;//取得IWorkbenchPage,并搜索使用editorInput对象对应的编辑器IWorkbenchPageworkbenchPage=getViewSite().
getPage();IEditorParteditor=workbenchPage.
findEditor(editorInput);/**如果此编辑器已经存在,则将它设为当前的编辑器(最顶端),否则*重新打开一个编辑器*/if(editor!
=null){workbenchPage.
bringToTop(editor);}else{try{workbenchPage.
openEditor(editorInput,editorID);}catch(PartInitExceptione2){e2.
printStackTrace();}}}});程序说明:在本程序中为了便于理解,使用了if…else这种简单的方式来判断双击的列表项,这适合列表项较少的情况,如果列表项太多了,则代码就会相当长.
解决这个问题,可将各IEditorInput对象与列表List的项对应起来,并将eidtorID写到各IEditorInput类中.
这样就可以用下面的方式来得到IEditorInput和eidtorID了.
Stringkey=""+list.
getSelectionIndex();IEditorInputeditorInput=(IEditorInput)list.
getData(key);StringeidtorID=editorInput.
getEditorID();18.
5.
5总结在实际开发中很多界面都是创建在编辑器上,虽然在这里只讲了最常用的编辑器使用方法,但以足够应付大部分开发的需要.
如果你想了解更多关于编辑器的信息,可以查阅编辑器的帮助文档,它在帮助中的位置是"平台插件开发者指南→程序员指南→编辑器".
18.
6编辑器类(EditorPart)方法使用说明在18.
5节将ChinaEditor类继承EditorPart抽象类时,只实现了两种方法:init、createPartControl,本节将通过"EditorPart方法的执行情况"、"各方法的作用及含义"、"一个实例"来逐步讲解其他的五种方法.
18.
6.
1EditorPart方法的执行情况要使用好EditorPart,首先得了解其方法在各种情况下的执行流程,我们在类的每一种方法前加上System.
out.
println("方法名:***"),运行后就可以得到如下的结果.
(1)双击列表项打开编辑器时:init→isDirty→createPartControl→isDirty→isDirty→isDirty→isDirty→isDirty→setFocus→isDirty→isSaveAsAllowed.
(2)关闭编辑器时:setFocus→isDirty→isSaveAsAllowed→isDirty→isSaveAsAllowed→setFocus→isDirty,如果保存编辑器,则最后还会执行doSave方法.
(3)单击编辑器标题时:setFocus.
(4)编辑器失去焦点时:isDirty→isSaveAsAllowed→isDirty→isSaveAsAllowed.
(5)编辑器得到焦点时:setFocus→isDirty→isSaveAsAllowed→isDirty→isSaveAsAllowed.
(6)当编辑器可以保存,并在主菜单"文件→保存"选项或按Ctrl+S键时:isDirty→doSave.
18.
6.
2各方法的作用及含义1.
booleanisDirty()由此方法获知编辑器是否脏了(所谓"脏"是指编辑器中的值已经发生了改变),true表示脏.
当其返回true时,会出现两个效果:编辑器的标题前出现一个"*"号,主菜单"文件"下的"保存"项可用.
特别要注意的是,编辑器不会自已判断是否脏了,这需要在程序中用语句手动设置,例如,在编辑器的文本框加入一个键盘监听事件,当在文本框中输入字符时,则将isDirty方法返回值设为true(脏).
在方法执行情况中,可以看到此方法的执行是最频繁的,所以不要在这种方法中加入太多的执行语句,否则会影响程序执行速度.
2.
voiddoSave()在这种方法中编写保存编辑器的代码,当在主菜单中选择"文件→保存"选项时会执行此方法,但在isDirty返回true时"保存"菜单和Ctrl+S键才可以用,也即isDirty方法控制着doSave方法的执行.
当保存成功时,要注意将脏的状态设回false,并调用firePropertyChange方法将编辑器的界面状态更新(编辑器标题前的"*"号及"保存"菜单).
3.
booleanisSaveAsAllowed()是否允许编辑器使用"另存为"功能.
如果此项返回false,则不能使用"另存为"功能,而且主菜单"文件"下的"另存为"项被置灰.
4.
voiddoSaveAs()和doSave的作用相似,在这里书写"另存为"功能的处理代码.
5.
voidsetFocus()当编辑器获得焦点时执行该方法.
18.
6.
3一个实例在这个实例中,当修改ChinaEditor编辑器中文本框的文字时,编辑器标题前出现"*"且主菜单"文件"下的"保存"选项可用.
当保存了编辑器后,"*"消失并且"保存"菜单不可用.
当编辑器为脏时,关闭编辑器会弹出一个提示框(如图18.
9所示).
图18.
9关闭脏编辑器时的效果图要实现以上效果只需要修改ChinaEditor类,修改后的代码如下:publicclassChinaEditorextendsEditorPart{privatebooleandirty=true;//编辑器是否为脏的标识//……init方法不变,省略/***在此方法中创建Editor中的界面组件*/publicvoidcreatePartControl(Compositeparent){CompositetopComp=newComposite(parent,SWT.
NONE);topComp.
setLayout(newFillLayout());Texttext=newText(topComp,SWT.
BORDER);text.
setText("中国之编辑器");text.
addKeyListener(newKeyAdapter(){publicvoidkeyPressed(KeyEvente){//如果编辑器不脏(即没有修改),则标志它脏并刷新界面状态if(!
isDirty()){setDirty(true);firePropertyChange(IEditorPart.
PROP_DIRTY);}}});}/***保存的处理代码在这种方法中,当按Ctrl+S键时会执行此方法.
*最后别忘记标志为非脏及刷新界面状态*/publicvoiddoSave(IProgressMonitormonitor){if(isDirty()){//……保存编辑器事件处理代码(省略)setDirty(false);firePropertyChange(IEditorPart.
PROP_DIRTY);}}/***是否允许"另存为"*/publicbooleanisSaveAsAllowed(){returnfalse;//不允许}/***"另存为"的代码写在这里,本例不实现它*/publicvoiddoSaveAs(){}/***dirty标识的set方法,由此方法设置编辑器为脏*/publicvoidsetDirty(booleandirty){this.
dirty=dirty;}/***编辑器的内容是否脏了.
true脏,false不脏*/publicbooleanisDirty(){returndirty;}/***当编辑器获得焦点时会执行此方法,本例空实现*/publicvoidsetFocus(){}}程序说明:firePropertyChange(IEditorPart.
PROP_DIRTY);这一句除了能将界面状态刷新之外,如果IEditorPart添加了如下的监听器,则还可以触发其中的propertyChanged事件.
chinaEditor.
addPropertyListener(newIPropertyListener(){//此时source为ChinaEditor对象,propId为IEditorPart.
PROP_DIRTY这个常量值publicvoidpropertyChanged(Objectsource,intpropId){//事件处理代码,省略}});18.
7加入首选项(preferencePages)选择主菜单"窗口→首选项"选项打开"首选项"窗口,如图18.
10所示.
这个窗口是Eclipse所有设置项的集中地,同样也常是第三方插件进行设置的窗口.
图中左边两个方框标注的就是SWTDesigner插件的设置树和本书插件MyPlugin的设置树.
本节将实现MyPlugin的首选项中的设置树.
图18.
10"首选项"窗口18.
7.
1修改plugin.
xml文件,设置首选项的扩展点打开plugin.
xml文件的编辑框,将如下代码块插入到最后一行的项之前:代码说明:org.
eclipse.
ui.
preferencePages是首选项的扩展点.
name是首选项的树结点的名称.
class是首选项的树结点所对应的类(还没编写,下一步将完成此类).
id是首选项的树结点标识,建议设置成和class一样的名称.
category是要等于父结点的id标识.
18.
7.
2建立首选项各结点对应的类在18.
7.
1小节的plugin.
xml中提前设置了首选项结点对应的类RootPreferencePage、DBPreferencePage,本小节就来在包cn.
com.
chengang.
preferences中创建此类.
首选项的类必须继承PreferencePage抽象类和实现IWorkbenchPreferencePage接口,实现接口只有一种方法init,抽象类则有一些"首选项"窗口的按钮的执行方法.
本小节实例先给出代码简单一些的根结点RootPreferencePage类,再给出复杂一些的子结点DBPreferencePage类,两类具体代码如下:文件名:RootPreferencePage.
java-publicclassRootPreferencePageextendsPreferencePageimplementsIWorkbenchPreferencePage{publicvoidinit(IWorkbenchworkbench){}protectedControlcreateContents(Compositeparent){CompositetopComp=newComposite(parent,SWT.
NONE);topComp.
setLayout(newRowLayout());newLabel(topComp,SWT.
NONE).
setText("欢迎使用myplugin2插件");returntopComp;}}文件名:DBPreferencePage.
java-publicclassDBPreferencePageextendsPreferencePageimplementsIWorkbenchPreferencePage,ModifyListener{//为文本框定义三个键值publicstaticfinalStringURL_KEY="$URL_KEY";publicstaticfinalStringUSERNAME_KEY="$USERNAME_KEY";publicstaticfinalStringPASSWORD_KEY="$PASSWORD_KEY";//为文本框值定义三个默认值publicstaticfinalStringURL_DEFAULT="jdbc:db2://127.
0.
0.
1/mydb";publicstaticfinalStringUSERNAME_DEFAULT="glchengang";publicstaticfinalStringPASSWORD_DEFAULT="12345678";//定义三个文本框privateTexturlText;privateTextusernameText;privateTextpasswordText;//定义一个IPreferenceStore对象privateIPreferenceStoreps;/***接口IWorkbenchPreferencePage的方法,负责初始化.
在此方法中设置一个*PreferenceStore对象,由此对象提供文本框值的读入/写出方法*/publicvoidinit(IWorkbenchworkbench){setPreferenceStore(Myplugin2Plugin.
getDefault().
getPreferenceStore());}/***父类的界面创建方法*/protectedControlcreateContents(Compositeparent){CompositetopComp=newComposite(parent,SWT.
NONE);topComp.
setLayout(newGridLayout(2,false));/**创建三个文本框及其标签*/newLabel(topComp,SWT.
NONE).
setText("URL:");urlText=newText(topComp,SWT.
BORDER);urlText.
setLayoutData(newGridData(GridData.
FILL_HORIZONTAL));newLabel(topComp,SWT.
NONE).
setText("用户名:");usernameText=newText(topComp,SWT.
BORDER);usernameText.
setLayoutData(newGridData(GridData.
FILL_HORIZONTAL));newLabel(topComp,SWT.
NONE).
setText("密码:");passwordText=newText(topComp,SWT.
BORDER|SWT.
PASSWORD);passwordText.
setLayoutData(newGridData(GridData.
FILL_HORIZONTAL));//取得一个IPreferenceStore对象ps=getPreferenceStore();/**取出以前保存的值,并将其设置到文本框中,如果取出值为空*或者是空字串,则填入默认值*/Stringurl=ps.
getString(URL_KEY);if(url==null||url.
trim().
equals(""))urlText.
setText(URL_DEFAULT);elseurlText.
setText(url);Stringusername=ps.
getString(USERNAME_KEY);if(username==null||username.
trim().
equals(""))usernameText.
setText(USERNAME_DEFAULT);elseusernameText.
setText(username);Stringpassword=ps.
getString(PASSWORD_KEY);if(password==null||password.
trim().
equals(""))passwordText.
setText(PASSWORD_DEFAULT);elsepasswordText.
setText(password);/**添加事件监听,this代表本类,因本类也实现了ModifyListener接口,*所以本类可以作为监听器使用*/usernameText.
addModifyListener(this);passwordText.
addModifyListener(this);urlText.
addModifyListener(this);returntopComp;}/***本类实现ModifyListener接口的方法,当三个文本框中发生修改时将执行此方法.
*方法中对输入值进行了验证并将"确定"、"应用"两按钮使能*/publicvoidmodifyText(ModifyEvente){StringerrorStr=null;//将原错误信息清空if(urlText.
getText().
trim().
length()==0){errorStr="URL不能为空!
";}elseif(usernameText.
getText().
trim().
length()==0){errorStr="用户名不能为空!
";}elseif(passwordText.
getText().
trim().
length()==0){errorStr="密码不能为空!
";}setErrorMessage(errorStr);//errorStr=null时复原为正常的提示文字setValid(errorStr==null);//"确定"按钮getApplyButton().
setEnabled(errorStr==null);//"应用"按钮}/***父类方法,单击"复原默认值"按钮时将执行此方法,取出默认值设置到文本框中*/protectedvoidperformDefaults(){urlText.
setText(URL_DEFAULT);usernameText.
setText(USERNAME_DEFAULT);passwordText.
setText(PASSWORD_DEFAULT);}/***父类方法,单击"应用"按钮时执行此方法,将文本框值保存并弹出成功的提示信息*/protectedvoidperformApply(){doSave();//自定义方法,保存设置MessageDialog.
openInformation(getShell(),"信息","成功保存修改!
");}/***父类方法,单击"确定"按钮时执行此方法,将文本框值保存并弹出成功的提示信息*@returntrue成功退出*/publicbooleanperformOk(){doSave();MessageDialog.
openInformation(getShell(),"信息","修改在下次启动生效");returntrue;}/***自定义方法,保存文本框的值*/privatevoiddoSave(){ps.
setValue(URL_KEY,urlText.
getText());ps.
setValue(USERNAME_KEY,usernameText.
getText());ps.
setValue(PASSWORD_KEY,passwordText.
getText());}}18.
7.
3运行插件运行插件后,打开新Eclipse环境的"首选项"窗口,选择"DB数据库"选项,将其中的密码删除后可得到如图18.
11所示的出错效果.
图18.
11首选项出错的效果图18.
7.
4总结本例程的核心是IPreferenceStore对象的使用,用它的getString方法来取值、setValue方法来存值.
其次和以前的事件代码写法有所不同的是:本类实现了ModifyListener接口,也成为了一个监听器,这样在各文本框的加入监听器的代码就会简洁很多,不过其事件代码必须保证三个文本框可以共用才行.
18.
8加入帮助(toc)如图18.
12所示,本节将为myplugin2插件加入帮助.
本节实例将演示如何在plugin.
xml添加扩展点,如何创建帮助左部的结点树,如何链接到帮助文件.
图18.
12帮助18.
8.
1修改plugin.
xml文件,设置三个帮助的扩展点打开plugin.
xml文件的编辑框,将如下代码块插入到最后一行的项之前:说明:org.
eclipse.
help.
toc是帮助的扩展点.
toc是帮助目录项的设定.
toc的file是指定帮助目录文件(还没编写,18.
8.
2小节将完成这两个xml文件).
toc的primary是该项帮助目录是否显示在帮助窗口中,true为显示.
如图18.
12所示左边的结点树,toc.
xml对应于"myplugin2帮助"结点,other_toc.
xml对应于"myplugin2的新版功能"结点.
18.
8.
2编写帮助目录文件toc这两个文件应放置在项目的根目录下,和src目录平级,如图18.
13所示.
图18.
13目录结构图先给出第一个文件toc.
xml的代码,如下:说明:topic:设置帮助目录中的结点.
topic的lable:结点显示的名称.
topic的href:结点对应的帮助文件的路径及文件名,也可以是网址(还没编写对应的帮助文档,18.
8.
1小节将完成它们).
这里应注意一个细微的地方:xml中项的结束符有两种,如或者是:这两者的效果是一样的.
下面再给出另一个帮助目录文件other_toc.
xml,代码如下:18.
8.
3创建相应的帮助文档帮助文件创建在插件项目的根目录下,和src目录平级,目录结构如图18.
13所示.
帮助文件都是一些标准的html格式的网页文件,这里仅给出项对应的1.
html文件,其内容如下:透视图一个链接在1.
html中,有一个链接"other/by_1_link.
html",这个文件并不需要在帮助目录文件toc.
xml中注册.
18.
8.
4总结创建帮助一般都分三步走:(1)在plugin.
xml添加扩展点.
(2)编写帮助目录的toc文件.
(3)编写相应的帮助文档.
还有一种做法是将帮助单独写成一个插件,这种插件和myplugin2插件没有什么不同,其开发过程也和本节一样,只不过该插件里只含有帮助的文件.
这种方式适合比较大的项目使用,因为分成了没有什么联系的两个插件,这样就可以让一批人开发myplugin2插件,另一批人开发帮助插件,两队人马互不干扰.
18.
9弹出信息式的帮助(contexts)弹出信息可以和窗口组件关联在一起,给用户显示有针对性的帮助,其效果如图18.
14所示.
如果组件设置有弹出信息,按F1键就可以激活它.
图18.
14弹出信息下面就以一个实例来演示如何实现弹出信息.
18.
9.
1修改plugin.
xml文件,设置弹出信息的扩展点打开plugin.
xml文件的编辑框,将如下代码块插入到最后一行的项之前.
代码说明:org.
eclipse.
help.
contexts是弹出信息的扩展点.
contexts的file指定弹出信息的设置文件(尚未编写,下一步将完成此xml文件).
18.
9.
2编写弹出信息的设置文件HelpContexts.
xmlHelpContexts.
xml文件应放置在项目的根目录下,和src目录平级.
编辑器视图代码说明:这里设置了两个弹出信息textHelpId、buttonHelpId.
id:弹出信息的标识.
description:弹出信息时的标题栏文字.
href:弹出信息子项所对应的帮助文件,可以和18.
8节的帮助文件共用,也可以自己设定单独的帮助文件.
视图编辑器图18.
15HelpContexts.
xml设置的效果图label:弹出信息子项的显示名称.
HelpContexts.
xml设置的效果如图18.
15所示.
18.
9.
3创建弹出信息对应的帮助文件由于在HelpContexts.
xml中,href项设置的都是18.
8节的帮助文件,所以本例此步省略.
18.
9.
4在界面组件中设置弹出信息在界面组件中设置弹出信息分成以下三步.
(1)弹出信息的准备工作已经完成,接下来是将它们和对应组件关联起来.
方法如下:WorkbenchHelp.
setHelp(text,"myplugin2.
textHelpId");第一个参数是组件对象名,第二个参数是弹出信息的id标识,前面要加上plugin.
xml的项设置的id标识.
(2)创建一个自定义Dialog来演示弹出信息.
代码如下:文件名:HelpContextsDialog.
javapublicclassHelpContextsDialogextendsDialog{protectedHelpContextsDialog(ShellparentShell){super(parentShell);}protectedControlcreateDialogArea(Compositeparent){CompositetopComp=newComposite(parent,SWT.
NONE);topComp.
setLayout(newRowLayout());//界面组件Texttext=newText(topComp,SWT.
BORDER);text.
setText("编辑器");Buttonbutton=newButton(topComp,SWT.
BORDER);button.
setText("打开视图");//让弹出信息和界面组件关联起来WorkbenchHelp.
setHelp(text,"myplugin2.
textHelpId");WorkbenchHelp.
setHelp(button,"myplugin2.
buttonHelpId");returntopComp;}}(3)编写打开此Dialog的方法,本例选择视图1上的一个按钮来打开Dialog.
在MyActionGroup类的Action1中的run方法中加入如下语句:HelpContextsDialogdialog=newHelpContextsDialog(null);dialog.
open();18.
9.
5运行插件运行插件后的效果如图18.
16所示.
图18.
16实例的弹出信息界面18.
9.
6总结设置弹出信息和设置帮助(toc)有其类似之处,而且它们的HTML格式的帮助文件也可以共用,但这并不是说弹出信息要依赖于帮助(toc)的设置.
而且不是所有的组件都支持弹出信息.
下面给出不支持弹出信息的组件例表:ToolItem;CtabItem;TabItem;TableColumn;TableItem;TableTreeItem;TreeItem.
18.
10本章小结本章介绍了插件中最常用的扩展点,不仅讲述了扩展点的含义,而且给出相应的实例和具体的实现步骤.
本章的每节组合在一起就是一个插件开发的开发流程,从透视图开始到帮助结束,插件开发大致是按照这个流程来走.
第21章项目打包与发行当项目完成后接下来的就是打包发行了,应用程序(Application)项目和Eclipse插件项目(plugin)的打包是不同的,本章将分别介绍两者的打包方法,并给出实际的打包例子.
7.
1应用程序项目的打包与发行7.
1.
1简介Java应用程序项目完成后是可以脱离Eclipse运行的,要运行程序先要打它打成一个JAR包,它打包的大部份方法和标准Java的AWT/SWING的打包方法一样,主要有以下几个要点zMANIFEST.
MF-打包清单.
它是打包的关键性文件,主要是设置执行入口类和支持库的路径,在运行Java应用程序时是要根据此文件中给出的信息来查找入口类和支持库.
z支持包-如果Java应用程序用到了一些Eclipse包,那么就必须将这些包也复制到程序运行目录,否则程序将无法运行.
如swt组件支持包swt.
jar,jface组件支持包jface.
jar.
这些包都要在MANIFEST.
MF文件中设置好.
z本地化文件-如果用到了SWT组件,则还需要将SWT的本地化文件swt-win32-3063.
dll(3063是版本号)复制到程序运行目录,否则程序将无法运行.
7.
1.
2打包的具体操作步骤本节将用前几章开发的SWT/JFace项目"myswt"的打包为例,来介绍打包应用程序项目的方法.
1、编辑清单MANIFEST.
MF(1)Eclipse提供了用于打包项目的"导出"向导,但本例运行此向导之前先需要创建一个MANIFEST.
MF清单文件,其内容如下:Manifest-Version:1.
0Main-Class:book.
chapter_4.
wizard_dialog.
WizardDialog1Class-Path:.
/lib/swt.
jar.
/lib/jface.
jar.
/lib/runtime.
jar说明:zManifest-Version-指定清单文件的版本号zMain-Class-指定程序运行的入口类.
本例设为运行4.
5.
2节开发的向导式对话框.
注意:类名后不要加class扩展名zClass-Path-指定支持库的路径.
".
"指程序运行目录,即导出的JAR包所在目录.
程序运行时依据Class-Path项的设置路径来查找支持库.
每一个支持库之间用空格隔开.
在这里jface.
jar需要用到runtime.
jar包,所以runtime.
jar包也要加入到Class-Path中.
z除了入口类的包名和类名之外,其他设置项都不分大小写,比如:Class-Path写成class-path或CLASS-PATH也可以,swt.
jar写成SWT.
JAR也行.
(2)将清单文件保存下来,建议放在myswt项目的根目录下.
它的文件名可以任意取,本例取名为manifes.
txt,Eclipse向导在打包时会自动的将manifes.
txt的内容复制到JAR包的META-INF目录下的MANIFEST.
MF文件中.
2、使用Eclipse"导出"向导来打包项目(1)右键单击myswt项目的项目名,在弹出菜单中选择"导出".
在弹出的如下图7.
1所示的对话框中,选择"JAR文件",单击"下一步".
图7.
1导出对话框(2)如下图7.
2所示,将右边不需要的文件都取消勾选.
在"选择导出目标"项文本框中设置JAR包的输出路径和包名(可以任意取名)为"D:myswt_applicationmyswt.
jar".
接受其他的默认设置不变,单击"下一步".
附注:左边虽然选择了src目录,但源文件并不会导出到包中,除非勾选了"导出Java源代码文件和资源"项.
图7.
2选择导入文件(3)如下图7.
3所示,接受默认设置不变,单击"下一步".
图7.
3导出类的选项(4)这一步较关键.
如下图7.
4所示,选择"从工作空间中使用现有清单"项,将创建的清单文件输入,也可以通过旁边的"浏览"按钮来选择清单文件.
输入清单文件后,单击"完成",Eclipse开始将项目打包.
图7.
4清单文件设置经过以上四步后,在"D:myswt_application"路径下生成了一个名为"myswt.
jar"的文件.
myswt.
jar是一个ZIP格式的压缩文件,可以用WinRAR或WinZip软件打开,也就是说用这两个软件也可以替代Eclipse向导来打包文件.
如果用WinRAR来打包文件,则压缩格式要选择ZIP格式而非RAR格式,压缩率倒可以任意选.
用WinRAR打开myswt.
jar文件后其内部的目录结构如下图7.
5所示:图7.
5myswt.
jar文件的内部目录结构在myswt.
jar文件的内部目录META-INF中仅一个文件:MANIFEST.
MF,它和以前创建的清单文件manifest.
txt的内容是一样的,如下:Manifest-Version:1.
0Class-Path:.
/lib/swt.
jar.
/lib/jface.
jar.
/lib/runtime.
jarMain-Class:book.
chapter_4.
wizard_dialog.
WizardDialog13、复制Java应用程序的支持包及本地化文件在MANIFEST.
MF文件中的Class-Path项设置了三个包,从Eclipse的plugins目录中将此三个支持包复制到D:myswt_applicationlib目录,本地化文件swt-win32-3063.
dll复制到D:myswt_application目录中.
此三个文件在Eclipse中的路径为:pluginsorg.
eclipse.
swt.
win32_3.
0.
1wswin32swt.
jarpluginsorg.
eclipse.
jface_3.
0.
0jface.
jarpluginsorg.
eclipse.
core.
runtime_3.
0.
1 untime.
jarpluginsorg.
eclipse.
swt.
win32_3.
0.
1oswin32x86swt-win32-3063.
dll复制完成后的目录结构如下图7.
6所示:图7.
6目录结构图4、编写运行myswt.
jar包的批处理程序"run.
bat"在myswt_application目录下创建一个批处理程序run.
bat(名字任取,扩展名必须是bat),其内容仅一句语句,如下:javaw-jarmyswt.
jar说明:zjavaw对应c:jdkjreinjavaw.
exe文件,如果windows提示命令未发现,则需要将c:jdkjrein路径加入到windows环境变量path中.
z在运行程序的时候有一个讨厌的黑色命令行窗口,要去掉它,可以将run.
bat内容更改如下:"startjavaw-jarmyswt.
jar",start是指调用了windows的"运行"命令.
z如果想将swt-win32-3063.
dll也放在单独的目录中,如"D:myswt_application ative"目录,则需将run.
bat内容更改为:startjavaw-Djava.
library.
path=.
/native/-jarmyswt.
jar5、运行程序双击run.
bat文件,得到如下图7.
7所示的程序界面.
图7.
7程序运行效果图6、注意事项本例只需要三个支持包,但你的程序也许会需要更多的支持包才能运行.
如果你想一次到位,则可以将"Java构建路径"的"库"选项卡中所有引用的包都复制到lib目录中.
如果你喜欢用到什么包才加入什么包,希望维持打包文件的简洁,则需要自己一步步的去试:如果缺少某支持包,运行程序时会输出的未找到类的错误信息,从信息中的包名可得知程序缺少哪一个支持包.
比如"Exceptioninthread"main"java.
lang.
NoClassDefFoundError:org/eclipse/jface/wizard/IWizard",从错误信息中很明显的就能知道程序缺少jface包7.
1.
3其他得到JAR包的方式要得到JAR包除了以上所说的用Eclipse"导出"向导、用WinZip和WinRAR,另外还能用Java自带的命令行式打包软件jar.
exe(位于c:jdkin目录),其打包命令为:c:jdkinjarcvfmmyswt.
jarC:eclipse3.
0.
1eclipseworkspacemyswtmanifest.
txt-CC:eclipse3.
0.
1eclipseworkspacemyswtin.
说明:zc:jdkinjar-由于本书没有把c:jdkin加入到windows环境变量path中,所以手工指定jar.
exe的路径zcvfm-jar.
exe的参数,"c"创建新的jar包;"v"将调试信息打印在屏幕上;"f"指定生成的jar文件名;"m"使用清单文件.
注意它们都是小写zmyswt.
jar-打包后的JAR包名z在前面是把清单文件manifest.
txt放在C:eclipse3.
0.
1eclipseworkspacemyswt目录下.
如果将它和批处理文件放在一个目录就不必指定长长的路径了.
z"-C路径.
"指将路径下(包括子目录)的所有文件打包,由于class文件是输出在项目的bin目录下,所以路径指定到项目的bin目录,注意三者之间是用空格隔开,并且最后一个字符是小数点.
这种方式的优点是没有Eclipse导出向导的操作那么麻烦,适合经常需要导出JAR包的情况.
7.
1.
4使用第三方插件对项目打包开源组织(http://sourceforge.
net/)中有一款可将Eclipse支持包和项目编译文件一起打到一个包中的插件,叫"FatJar",它的下载地址是"http://fjep.
sourceforge.
net/",具体下载不再说明,安装步骤参阅第1章SWTDesigner的安装.
FatJar的使用步骤如下:(1)右键单击myswt项目的项目名,可见菜单中多了一项"BuildFatJar",如下图7.
8所示,选择"BuildFatJar"项.
图7.
8右键菜单(2)在下图7.
9所示的对话框中,"Jar-Name"项填入JAR包的输出路径.
文件清单"Manifest"项不用填,默认会自动创建一个.
"Main-Class"项填入程序的入口类.
其他都接受默认值,单击"下一步".
图7.
9输出配置(3)如下图7.
10所示,窗口中将myswt项目所用到的支持包都列了出来.
我们仅勾选图中runtime.
jar、swt.
jar、jface.
jar这三项即可,当然全选也并尝不可,只是最后得到的JAR包会更大一些,因为FatJar会将所有支持包合并在一个JAR包中.
图7.
10选择要打包的文件单击图7.
10的"完成"按钮后,JAR包myswt.
jar将输出到D:myswt_applicationh目录中.
和以前一样,要运行此JAR包需要一个批处理文件以及本地化文件swt-win32-3063.
dll,唯一不同的是不再需要Eclipse支持包,其目录结构如下图7.
11所示:图7.
11目录结构为什么不需要Eclipse支持包了呢那是因为支持包已经在myswt.
jar文件中了,从下图7.
12可以看到swt.
jar等都被拆散成目录,并包含在myswt.
jar包中.
图7.
12myswt.
jar的内部目录结构其中META-INF目录的MANIFEST.
MF文件内容如下,可以发现和以前不同的地方是:Class-Path项没有了.
Manifest-Version:1.
0Created-By:FatJarEclipsePlug-InMain-Class:book.
chapter_4.
wizard_dialog.
WizardDialog17.
1.
4让用户电脑不必安装JRE环境通常运行Java程序有个前提条件:用户电脑必须先安装JRE环境.
虽然安装JRE环境非常简单,但毕竟多了一步,算是有一点点的瑕疵.
这里给出一个不必让用户安装JRE环境的方法,其实现步骤如下:(1)将原JDK中的"jre"目录复制到"D:myswt_applicationjava1.
4.
2"目录下(java1.
4.
2也可换成其他名称).
(2)将JDK和JRE从本机卸载掉,这样表示本机没有安装JAVA运行环境.
(3)修改批处理文件run.
bat中的命令为"startjava1.
4.
2jreinjavaw-jarmyswt.
jar",仅仅是在javaw前加上了一个相对应路径.
双击run.
bat即可在不安装JRE环境的电脑运行此Java应用程序.
7.
1.
5更进一步的完善1、抛弃批处理文件(*.
bat)用批处理文件运行程序似乎不够专业,虽然它足以完成运行任务.
但习惯就象一种毒药一旦染上就很难摆脱它的影响,Windows统治下的人们早已经习惯运行扩展名是EXE的程序,用*.
bat他们就会感觉别扭.
我们可以用一个叫JavaLauncher的免费小程序来代替批处理文件去运行Java程序.
JavaLauncher的下载网址是:http://www.
rolemaker.
dk/nonRoleMaker/javalauncher/marner_java_launcher.
htm下载下来的文件是一个名JavaLauncher.
zip的压缩包,解压后的目录结构如下图7.
13所示:图7.
13JavaLauncher.
zip目录结构在上图的目录中zsource目录包含了JavaLauncher的源程序,是用C语言写的zchanges.
txt是新版的修改说明zlaunch.
exe是主程序zlauncher.
cfg是配置文件zreadme.
txt是一些说明和示例我们只需要launch.
exe、launcher.
cfg两个文件,将这两个文件复制到打包文件所在的目录.
launcher.
cfg是一个仅三行内容的文本文件,将它修改如下:.
.
java1.
4.
2jreinjavaw.
exe-jarmyswt.
jarz第一行设置指向JAR包myswt.
jar的目录,由于launch.
exe和myswt.
jar同在一个目录,所以用".
"即当前目录.
z第二行设置指向jreinjavaw.
exe的路径.
在上一小节(7.
1.
4节)已将jre目录复制到了java1.
4.
2子目录中配置好launcher.
cfg后,双击launch.
exe即可运行java应用程序.
如果仔佃研究eclipse的启动方式,发现eclipse和JavaLauncher的原理一样:eclipse.
exe相当于launch.
exe,startup.
jar相当于myswt.
jar.
只不过eclipse.
exe不象launch.
exe要具有通用性,所以它没有*.
cfg这样的配置文件,而是将启动信息固化在eclipse.
exe中.
2、美化图标launch.
exe文件的图标太单调了,让我们给它换个好看点的.
换程序的图标需要用到一个免费的软件:ResourceHacker,它有中文版,下载网址是:http://www.
users.
on.
net/johnson/resourcehacker/用ResourceHacker来替换launch.
exe的图标的步骤如下:(1)运行ResourceHacker,得到如下图7.
14所示的窗口.
图7.
14ResourceHacker的主界面(2)单击主菜单"文件→打开",将launch.
exe载入到程序中,结果如下图7.
15所示.
图7.
15载入Lanunch.
exe之后的界面(3)如上图,选择左边的"图标→1→1030",然后右键单击"1030"项,选择"替换资源…".
如下图7.
16所示,在弹出窗口中单击"打开新图标文件",选择一个满意的图标,然后单击"替换"按钮.
附注:图标文件可以是exe、dll、res、ico,该软件可以从exe、dll、res抽取出图标,本例选择的是java的一个图标文件JavaCup.
ico.
图7.
16选择图标文件(4)如下图7.
17所示,选择"文件→另存为",取名myswt.
exe.
附注:按理说选择"保存"也是可以的,这时ResourceHacker会将老的launch.
exe备份成launch_original.
exe.
但也许是刷新上有问题,用"保存"方式有时launch.
exe无法显示出新图标,但有时又可以.
图7.
17保存修改(5)最后的目录如下图7.
18所示,可见myswt.
exe(也就是launch.
exe改了个名称)的图标换成了Java的图标.
双击myswt.
exe即可运行Java应用程序.
图7.
18最后的效果3、最后的打包发送给用户之前,通常要用WinZip或WinRAR将所有的文件全部打成一个压缩包,然后用户得到这个压缩包后,将其解压缩后即可运行程序,Eclipse软件就是这种方式.
另一种方式是用InstallShield、InstallAnyWhere这样的安装程序制作软件来创建一个单一的setup.
exe文件,它具有向导式的安装界面,而且还可以往windows的程序栏插入菜单项,关于这些安装程序制作软件的具体使用请参阅相关书籍.
第9章Eclipse的J2EE开发Eclipse默认安装是没有J2EE开发支持的,它需要安装第三方插件,本章的主要介绍的J2EE开发插件是Lomboz,主要开发环境是Tomcat+Lomboz+Struts+Hibernate,这是当前比较流行的一种选择.
其中Tomcat充当WEB服务器;Lomboz是J2EE开发的工具;Struts提供强大的MVC模式支持;Hibernate替代笨重的EJB来充当数据库的持久层.
以上所有的工具和软件包不仅流行、功能强大、而且是免费的,是J2EE开发典型搭配.
本章将分三个层次来渐进式的展开讲解:zLomboz下的纯J2EE开发z融合Struts的J2EE开发z融合Struts和Hibernate后的J2EE开发由于篇幅有限,本章以开发环境的安装和配置为重点,并辅以一个典型而有深度的实例来演示具体的开发操作,最后给出一个扩展知识的资料索引.
本章和第8章一样也使用CVS来管理所有例程,在每一节的标题后会用括号显示这一节的版本号.
本章具体的环境为:WindowsXP+JDK1.
4.
2_06+Eclipse3.
1M4+cvsnt2.
0.
58d+Tomcat5.
0.
28+Lomboz3.
1.
0+Struts1.
2.
4.
9.
1WEB环境的搭建(V0010)9.
1.
1下载CVS版本注意事项由于V0010版,存在一些空目录,而这些空目录也是必须要的,否则项目会出错.
这需要修改一个CVS的配置,如下图9.
1所示,打开Eclipse的首选项→小组→CVS→将"修剪空目录"项取消勾选.
图9.
1修改CVS配置9.
1.
2Tomcat的下载与安装这一节先搭建好Tomcat环境,Tomcat的下载安装和Eclipse、Lomboz都没有直接关系,它是完全独立的.
1、下载Tomcat(1)用IE打开Tomcat的下载页面:http://jakarta.
apache.
org/tomcat/index.
html,选择页面左边的链接"Binaries",转到下图9.
2所示的页面:图9.
2Tomcat项目选择(3)单击上图中标识的"Tomcat"项,出现如下图9.
3所示的页面图9.
3具体下载项(4)下载上图9.
3所示的"5.
0.
28.
exe"项,下载后的文件名为:jakarta-tomcat-5.
0.
28.
exez注意:z(1)不要下载Tomcat5.
5.
*版,因为那需要JDK5.
0的支持;也不要下载4.
1.
*版,它的功能太弱了.
因为不同版本之间的安装和配置都会有所不同,为了和本教程同步,一定要下载5.
0.
28版.
z(2)如果用FlashGet等多线程下载工具无法下载,则改用原始的IE右键菜单的"另存为…"项来下载.
2、安装Tomcat安装Tomcat的过程比较简单,双击得到的下载文件:jakarta-tomcat-5.
0.
28.
exe,开始安装.
(1)选择安装组件.
接受默认的勾选即可,如下图9.
4所示.
图9.
4选择组件(2)选择Tomcat安装目录.
也一样接受默认值,将安装到C:ProgramFilesApacheSoftwareFoundationTomcat5.
0目录下,如下图9.
5所示:图9.
5Tomcat的安装目录(3)选择HTTP监听端口(Port),如下图9.
6所示.
默认端口是8080,如果8080端口已被你电脑上的其他软件所占用(如IIS、JBoss等),则可以另选择一个空闲的端口.
最后,给Tomcat的超级管理员admin设为一个密码(本书设为123456).
图9.
6设置端口和密码(4)设置Tomcat使用的JVM,本书的默认值为"C:ProgramFilesJavaj2re1.
4.
2_06",如下图9.
7所示.
很多资料都指出,在安装JDK时要设置设置classpath、JAVA_HOME、path等环境变量,但本书从第一章开始就从没有设置过这些环境变量,一样可以运行通畅,也许是新版的JDK1.
4.
2_06很好的解决了这些问题.
从这一步也可以看到,Tomcat已经在安装时定位好了JVM的位置,不必再手工设置了.
设置好JVM后,单击"install"按钮,开始安装.
图9.
7定位JVM的位置(5)安装完成之后,在Windows的"控制面板"→"管理工具"→"服务"窗口中,可以看到Tomcat已经注册为windows的一项服务,如下图9.
8所示.
请确定它是"手动"方式,这一点在开发时很重要,因为我们以后要通过Eclipse来启动Tomcat.
图9.
8windows"服务"窗口3、启动Tomcat虽然以后在开发时,是要通过Eclipse来启动Tomcat,但现在为了测试Tomcat是否安装成功,暂时先启动Tomcat.
(1)可以通过Windows的"开始"菜单→"ApacheTomcat5.
0"组→"ConfigureTomcat"项来运行Tomcat的配置界面(如下图9.
10所示),这个界面包含了Tomcat的一些参数设置,这些设置一般都不用去改动它.
直接"单击"按钮,即可启动Tomcat.
图9.
10Tomcat的配置界面(2)在IE浏览器中输入"http://localhost:8080"或"http://127.
0.
0.
1:8080",其中8080为安装时设置的端口号.
如果启动成功,则会出现如下图9.
11所示的页面;反之,如果没有出现此页面,则表示启动未成功,这时你需要检查前面的安装步骤是否和本书的一致.
图9.
11验证Tomcat是否安装及启动成功附注:在上图页面的左部有两个链接:TomcatAdministration、TomcatManager,它们是用于管理Tomcat的,登录密码都是在安装Tomcat时设置的用户名admin和密码123456.
其中,TomcatAdiministration项可以设置数据库连接池、管理用户及权限、以及其他一些Tomcat服务器相关设置;TomcatManager项主要用来发布网页管理,通过它可以轻松的将一个WAR包发布到Tomcat中.
关于Tomcat中文问题的解决,请参阅9.
4.
6节.
9.
1.
3Lomboz的下载与安装下载Lomboz时一定要针对Eclipse的版本来选择相应的Lomboz版本下载,否则对应版本不同,很有可能会导致Lomboz无法正常使用.
本章由于依然要使用CVS,所以还是用Eclipse3.
1M4版,Lomboz选择相应的3.
1.
0版.
1、下载LombozLomboz的下载地址是:http://forge.
objectweb.
org/project/showfiles.
phpgroup_id=97,下载页面如下图9.
12所示,请选择forEclipse3.
1.
x的Lomboz来下载,而且还需要同时下载emf包(如图中箭头所示).
下载后的文件名为:zorg.
objectweb.
lomboz_3.
1.
0.
N20050106.
zipzemf-sdo-runtime-I200412160800.
zip图9.
12Lomboz的下载页面2、安装Lomboz(1)因为Lomboz、emf是Eclipse的插件,所以它和其他Eclipse插件的安装方法一样,本书采用Links式的插件安装方法,具体步骤不再重复,请参阅1.
2节的安装步骤.
下图9.
13是安装完成后的目录结构:图9.
13lomboz、emf的安装目录结构其中图9.
13中的links目录有新创建的两个文本文件:z文件lomboz.
link,内容仅一句:path=lomboz_3.
1.
0.
N20050106z文件emf.
link,内容也仅一句:path=emf-sdo-runtime-I200412160800(2)验证Lomboz是否安装成功启动Eclipse.
如果安装成功,选择"文件"→"新建"→"项目"会出现如下图9.
14所示的Lomboz项目.
图9.
14验证Lomboz是否安装成功(3)如果未能出现上图画面,请做如下检查和尝试:z删除eclipse目录下的子目录configuration,再启动Eclipse试一试.
z检查Lomboz的版本是否和Eclipse的一致.
zLinks文件中的path项是否设置正确.
zLomboz的目录结构是否正确:.
.
lomboz_3.
1.
0.
N20050106eclipseplugins,注意lomboz_3.
1.
0.
N20050106和plugins的中间还有个elcipse目录.
9.
1.
4Lomboz的环境设置安装完Lomboz之后,还需要针对Tomcat做一些设置才能用于开发WEB,具体操作步骤如下:(1)打开Eclipse的首选项,设定JDK的tools.
jar包的位置,本书是"C:jdklib ools.
jar",如下图9.
15所示:图9.
15设定JDK的tools.
jar包的位置(2)如下图9.
16所示,注意,在Servertypes项的下拉框中,要选择和当前所用Tomcat版本相对应的项;ApplicationServerDirectory和ClasspathVariable两项都是指向Tomcat的安装目录:C:ProgramFilesApacheSoftwareFoundationTomcat5.
0.
图9.
16Tomcat在Lomboz中的设置(3)Tomcat5.
0.
28版本在Lomboz中无法启动,必须还要做一些小修改.
到Lomboz插件的".
.
lomboz_3.
1.
0.
N20050106eclipsepluginscom.
objectlearn.
jdt.
j2ee_3.
0.
1servers"目录中,可以看到各种Web服务器的配置文件,它们都会显示在上图9.
16的servertypes下拉框中,除了tomcat50x.
server文件外,其他都不需要,把它们都删除掉或者备份到其他地方.
最后,用记事本打开tomcat50x.
server,并将所有"${serverRootDirectory}/bin;${serverRootDirectory}/common/endorsed"项替换成"${serverRootDirectory}/common/endorsed",共有两处,约在文件中的35、39行位置.
9.
1.
5JSP的HelloWorld本小节将写一个JSP的HelloWorld,用来验证以上Tomcat和Lomboz的环境是否安装成功.
1、设置Java的构建路径打开Eclipse首选项,如下图9.
17所示,选择"java"→"构建路径"→选择"文件夹"项.
经过此步设置之后,新建的Java项目(包括J2EE项目)就会默认以bin为输出目录.
z注意:这一步相当重要,因为用Lomboz创建J2EE项目时,是无法象创建普通Java项目那样选择"项目布局"的,此时J2EE项目的输出目录将会是在项目根目录下,以后JavaBean的java文件也会和class文件混在一块,非常不便.
更关键的是,在后面会要重新定位JavaBean的输出路径,如果不经过这一步,则定位JavaBean的输出路径时,整个项目的输出路径也会自动定位到bin目录下,但此时项目结构都会调整,容易导致混乱.
总之,此步一定不能省略.
图9.
17设置Java项目的构建路径2、创建一个J2EE项目(1)重启Eclipse.
选择"文件"→"新建"→"项目",选择如下图9.
18所示的"LombozJ2EEProject"项目,然后单击"下一步".
图9.
18选择"LombozJ2EEProject"项目(2)输入项目名称myweb,然后单击"下一步".
(3)在接下的"定义Java构建设置"页中不做任何改变,直接单击"下一步".
(4)最后一个页面是J2EE的设置,如下图9.
19、9.
20所示.
共有三步:创建一个名为hello的WebModules(WEB模块);在TargetedServers选项卡中,选择"ApacheTomcatv5.
0.
x"项并单击"Add"加入;单击"完成"按钮,开始生成一个J2EE项目.
图9.
19创建一个WebModules图9.
20设置TargetedServers(5)完成以上操作之后,"包资源管理器"视图中会出现如下图9.
21所示的项目结构.
图9.
21myweb项目的项目结构3、在Lomboz中启动Tomcat右键单击"hello模块",弹出如下图9.
22所示的右键菜单,选择RunServer来启动Tomcat(启动前确保Tomcat还是停止状态).
在这个菜单中还有其他常用的菜单项:zStopServer-停止TomcatzDebugServer-用调试方式启动Tomcat.
在WEB开发中,它比RunServer更常用.
zCheckAllJSPSyntax-检查项目中所有JSP文件的语法是否符合规范zUndeployModule-删除已经发布在Tomcat上的WEB模块zDeployModule-发布WEB模块到Tomcat上zShowinBrowser-在IE中预览本WEB模块的效果.
图9.
22hello模块的右键菜单如果启动Tomcat成功,在控制台会显示如下图9.
23所示的字符串.
图9.
23控制台的输出显示4、发布hello模块右键单击hello模块,打开如上图9.
22所示的右键菜单,选择DeployModule项,将hello模块发布到Tomcat.
从下图9.
24的控制台输出,可以看出Lomboz使用Ant来发布网页,每一行都显示出hello模块的打包发布过程,下面给出一些关键词解释:zmkdir-创建目录zcopy-复制文件zjar-用JDK的jar来打包(这里是打包成hello.
war)zdelete-删除文件图9.
24发布hello模块时的控制台输出再次调出hello模块的右键菜单,选择ShowinBrowser项.
Lomboz将打开IE浏览器,得到如下图9.
25所示的效果,也可以直接打开IE浏览器,输入地址"http://127.
0.
0.
1:8080/hello/"来查看效果.
这个页面显示的是index.
jsp文件.
图9.
25用IE来查看网页效果5、修改index.
jsp如下图9.
26所示,修改index.
jsp来显示一个HelloWorld字符串.
图9.
26修改index.
jsp保存好之后,还要再用"DeployModule"菜单项重新发布hello模块,然后才能在IE中看到修改后的效果.
6、一些相关问题(1)如果看不到修改效果,有可能是IE的页面缓存的原因,可以尝试如下解决办法:关掉IE,然后再打开,进入"工具"→"Internate选项",单击下图9.
27中的"删除文件"按钮来删除IE的网页缓存.
图9.
27删除IE页面缓存(2)同样是因为缓存原因,在停止Tomcat服务后,即使刷新网页却依然能正常显示.
将IE关掉重启,页面即会无法访问.
(3)如果是在Eclipse中启动Tomcat的,则关闭Eclipse,Tomcat服务也随之停止.
但建议还是使用"StopServer"菜单项来正常停止Tomcat服务.
9.
1.
6如何不必发布就可以在IE上显示WEB修改效果经过前面设置后,虽然可以开发WEB了,但每一次修改都要重新发布hello模块,才能在IE上显示修改后的效果,这无疑是开发时无法接受的,照这样,开发的时间进度至少要增加一倍.
本小节将给出不必不发布就可以在IE上显示修改效果的方法.
首先,解决的办法是基于以下知识的:z在发布hello模块时,Lomboz是将hello模块打成一个WAR压缩包,然后复制到Tomcat的webapps目录,在IE上显示的网页就是来自于这个目录下的WAR压缩包中,所以不能直接显示修改后的JSP文件也是可以理解的了.
zTomcat要发布网页,不是必须得打成WAR包,也可以发布未经压缩的文件目录.
实际项目中,直接发布零散文件的方式居多,因为这样更新JSP文件比较方便.
z在Tomcat安装目录下的conf子目录里有一个名为server.
xml的文件,它可以用来定义一个新的WEB应用.
由上面的知识,可以得出以下解决思路:通过修改server.
xml文件,定义一个新的WEB应用,将这个WEB应用定位到Eclipse的workspace目录中的myweb项目.
这样设置以后,IE显示的文件就是Eclipse中正在编写的JSP文件了,也就是说,不必再经过打包成WAR发布这一步.
具体操作步骤如下:(1)为了避免干扰,先将原来发布的hello模块删除.
打开Tomcat主页面:http://127.
0.
0.
1:8080/.
选择链接"TomcatManager",输入用户名密码(admin、123456),得到如下图9.
28所示页面.
单击hello模块右侧的"Undeploy"将hello模块从Tomcat上的撤消发布.
图9.
28撤消Tomcat上的hello模块(2)修改server.
xml,定义一个新的WEB应用server.
xml此文件的具体路径如下:C:ProgramFilesApacheSoftwareFoundationTomcat5.
0confserver.
xml.
此server.
xml文件最未尾的项之前插入一项的设置,的具体代码如下:代码说明:z注意一定要将以上代码加在紧靠项之前,的几个属性可以分行写,也可以写成一行.
zpath-是指WEB模块的名称hello,这样其访问地址为:http://127.
0.
0.
1:8080/hello/zdocBase-定义jsp文件位置.
本处指向Eclipse中hello模块的路径zworkDir-在IE显示之前,JSP要先编译成servlet,这个属性就是定义hello模块输出的servlet的所在位置.
如下图9.
29所示,因为所建的myweb项目默认的输出路径为mywebin目录,所以这里的workDir也定位到此mywebin目录.
图9.
29myweb项目的默认输出文件夹(4)右键单击"hello"模块→选择LombozJ2EE→选择DebugServer(或RunServer).
然后,在IE浏览器中输入"http://127.
0.
0.
1:8080/hello/"来查看效果.
最后,随便修改一下index.
jsp文件,直接刷新一下IE,如果可以看到修改后的效果,表示以上所有设置成功.
如下图9.
30所示的"导航器"视图(注意:不是"包资源管理器"视图),index.
jsp在经过IE显示之后生成几个新文件和目录(可能需要先刷新一下myweb项目):图9.
30myweb项目结构9.
1.
7配置Tomcat的数据库连接池在WEB开发中,有没有数据库连接池对WEB性能的影响非常大,Tomcat有自带的连接池,这一节就来配置Tomcat的连接池.
1、复制JDBC连接包将第8章使用的JDBC连接包mysql-connector-java-3.
0.
16-ga-bin.
jar复制到C:ProgramFilesApacheSoftwareFoundationTomcat5.
0commonlib目录下,commonlib是Tomcat的全局引用库的所在目录,Tomcat在启动时会自动加载这个目录中的所有JAR包.
有些网上的文章说也可以将数据库连接包复制到WEB应用的WEB-INFlib中(本例的mywebhelloWEB-INFlib目录),这个目录是hello模块发布时会自动加载的一个包目录.
但经笔者实验,如果连接包将放在此目录中,不用数据库连接池方式来访问数据库,则连接包可以正常使用;如果使用Tomcat连接池,则会出错误,连接包无法使用.
2、进入Tomcat的配置页面用IE浏览器输入地址:http://127.
0.
0.
1:8080/admin/,打开Tomcat服务器配置的登录页面,再输入用户名admin、密码123456,进入Tomcat的配置页面,如下图9.
31所示:图9.
31连接池设置单击左边的树结点"DataSource"→选择右上角的下拉框的"CreateNewDataSource"项,然后在表格中输入相应的连接池配置信息:zJNDIName:jdbc/mysql-设置连接池的JNDI名,在Java程序会用到此名.
zDataSourceURL:jdbc:mysql://localhost/sms-数据库连接字串,sms是数据库.
zJDBCDriverClass:com.
mysql.
jdbc.
Driver-JDBC连接类.
zUserName:root-数据库登录用户名.
zPassword:数据库登录密码.
本例为123456.
zMax.
ActiveConnections:4-最大连接数.
实际应用时,应该根据WEB使用情况设置得大一些;开发时,4个连接足够了.
zMax.
IdleConnections:2-最大空闲连接数.
zMax.
WaitforConnection:5000-最大等待连接限制.
zValidationQuery:验证用的查询语句,可以不填.
填写完以上信息之后,单击右下角的"Save"按钮保存修改,再单击右上角的"CommitChanges"按钮提交修改.
3、修改Tomcat的server.
xml文件server.
xml文件的具体路径:C:ProgramFilesApacheSoftwareFoundationTomcat5.
0confserver.
xml,在原来的项中加入一个子项:4、测试数据库连接池将以下测试程序命名为test.
jsp,创建在hello模块的根目录下,然后通过IE地址:http://127.
0.
0.
1:8080/hello/test.
jsp来访问.
这个测试程序从数据库连接池中获得一个数据库连接对象Connection,然后再查询数据库的iuser表,并用name(姓名)列的数据打印出来(注:iuser是在第8章创建的用户表).
test.
jsp运行效果如下图9.
32所示:图9.
32test.
jsp的效果test.
jsp源代码如下:程序说明:z这一行是设置网页的字符集,也是解决中文乱码问题的关键一句.
如果是纯html页面,则应在项之前加入这样一句:.
z这一句类似于Java中的importjava.
sql.
*.
zctx.
lookup("java:comp/env/jdbc/mysql");这一句中comp/env是固定不变的,jdbc/mysql是前面连接池设置的JNDIName.
z在程序最后一定要关闭数据库连接(实际是将连接返回给连接池,并没有真正关闭),否则,很快就会因连接数耗尽,而无法再正常显示JSP页面.
今天再帖出在"插件项目实战"一章中关于建模的.
内容虽然简单,但其中的方法我认为还是很重要的,因为在浏览很多帖子发现在建模时,还是有不少争论的,我估计至少有70%的Java程序员,无法很好的做到面向对象设计和分析,本节多少也反映了我的一些经验和观点吧,希望对大家有所帮助.
8.
2面向对象分析和数据表创建(版本V0010)8.
2.
1界面效果及实现功能本章项目是编写一个学生成绩管理软件,由于主要目的是给出一个项目开发的示例,所以这个软件的功能是做得相当简单的,也不存在需求分析阶段.
关于学生成绩管理软件的一些功能及概念,也不再多加说明,毕竟大家都是从学校和考试里走出来的,对这些已经很熟悉了.
本章项目的主体界面框架如下图8.
19所示:图8.
19主体界面框架功能说明:z左上部是主功能导航器视图(简称为主功能导航器或主功能视图),其中提供了一个功能结点树,本章将实现"档案管理"和"成绩管理"两个结点的功能.
z右部是一个编辑器,当单击"档案管理"结点时将生成一个编辑器.
z左下部是成绩管理的搜索视图,可以根据这个视图设置的搜索条件,查询出相应的考试成绩.
z右部还有一个名为"2003-12-11段考"的编辑器,当单击左下部的"搜索"按钮时将生成此编辑器,如下图8.
20所示:图8.
20成绩编辑器8.
2.
2面向对象的分析与设计面向对象的分析与设计,也称OOAD(ObjectOrientedAnalyseDesign).
因为它能够更准确自然的用软件语言来描述现实事物,并使得在它基础上构建的软件具有更好的复用率、扩展性及可维护性,所以OOAD是当前最重要的软件方法学之一.
OOAD和Rose、Together等UML软件没有必然的关系,OOAD是一种方法,UML是描述这种方法的图形语言,而Rose等则是使用UML的具体工具.
OOAD的关键在于思维方式的转变,而不是工具的使用,即使只用铅笔和白纸也可以成为一个优秀OOAD专家.
现在大学的课程以C、Basic、VB、FoxPro居多,即使是用C++、Java,也是可以用面向过程的方式来编写程序,所以使用面向对象的语言并不代表你是以面向对象的方式来思考和编程.
徒具对象的形,而无对象的神,是现在一般程序员的最大缺陷所在.
以本项目为例,大多数习惯于面向过程的编程思维方式的开发人员,一般在做完需求分析后,便开始设计数据库的表结构,而在编码阶段才开始考虑根据表结构来进行对象的设计与创建,这种开发方式就是带有过去很深的面向过程、面向数据库表编程的烙印.
所谓"万物皆对象",OOAD应该是把对象做为思考的核心,而不是仅仅把"对象"当成一种编程的手段,应当先完成对象设计,然后再根据对象创建表,这是最基本的次序.
当然这种方式在转化成数据库时会遇到一些困难和阻力,毕竟数据库不是面向对象的,SQL语言也不是面向对象的.
但Hibernate、JDO、EJB等数据库持久化技术,已经可以让开发者用完全的面向对象方式来编程,而不必忍受"对象"到"关系"转化的痛苦.
为了让读者可以了解如何手工完成"对象"到"关系"的转化,本插件项目仍然使用纯JDBC方式来实现.
在第9章会讲解Hibernate的使用,所谓"先苦后甜",通过两种方式的比较,读者能更深的体会Hibernate等数据库持久化技术的美妙之处.
本章的学生成绩管理软件有以下对象:学生、老师、年级、班级、课程、成绩、考试,本项目所有对象创建在cn.
com.
chengang.
sms.
model包下,如下图8.
21所示.
接下来会具体分析一下这些对象,并给出其源代码和UML类图.
图8.
21数据对象所在的包1、用户对象:学生、老师这个系统有可能会存在一个前台网站,比如:老师用Eclipse做客户端来管理成绩,而学生则通过一个网页来查询成绩,所有的数据集中在学校的中心服务器上.
因此系统的用户有两种:学生、老师,这两种用户有一些信息是相同的,有些则不同.
比如他们都有用户名、姓名、密码等,而学生没有老师的课程属性,老师则没有学生的班级属性.
由上面的分析,我们将两种用户的共性抽象成一个接口:IUser,这个接口有如下属性:数据库ID号(Id)、用户名(userId)、密码(password)、姓名(name)、最后登录时间(latestOnline).
另外,学生类(Student)有班级属性(SchoolClass),老师类(Teacher)则有课程(Course)属性,学生类和老师类都实现于IUser接口.
将用户抽象成一个接口的另一个好处就是:使用户类置于同一个规范之下.
今后要新增加一个种类型的用户,比如:家长用户,只需要再实现IUser接口即可.
"接口"是用Java进行OOAD开发的一个最重要的概念,也是成为一个优秀的Java设计师所必须掌握和熟练使用的概念.
其他说明:类的实例变量有多种叫法:通用的名称是"实例变量"或"属性";在实体类中因为和数据表的字段相对应,也可称之为"字段";有些书籍文章也称之为"域".

百纵科技:美国独立服务器租用/高配置;E52670/32G内存/512G SSD/4IP/50M带宽,999元/月

百纵科技怎么样?百纵科技国人商家,ISP ICP 电信增值许可证的正规公司,近期上线美国C3机房洛杉矶独立服务器,大带宽/高配置多ip站群服务器。百纵科技拥有专业技术售后团队,机器支持自动化,自助安装系统 重启,开机交付时间 30分钟内交付!美国洛杉矶高防服务器配置特点: 硬件配置高 线路稳定 洛杉矶C3机房等级T4 平价销售,支持免费测试,美国独服适合做站,满意付款。点击进入:百纵科技官方网站地...

pacificrack:超级秒杀,VPS低至$7.2/年,美国洛杉矶VPS,1Gbps带宽

pacificrack又追加了3款特价便宜vps搞促销,而且是直接7折优惠(一次性),低至年付7.2美元。这是本月第3波便宜vps了。熟悉pacificrack的知道机房是QN的洛杉矶,接入1Gbps带宽,KVM虚拟,纯SSD RAID10,自带一个IPv4。官方网站:https://pacificrack.com支持PayPal、支付宝等方式付款7折秒杀优惠码:R3UWUYF01T内存CPUSS...

Spinservers:美国独立服务器(圣何塞),$111/月

spinservers是Majestic Hosting Solutions,LLC旗下站点,主营美国独立服务器租用和Hybrid Dedicated等,spinservers这次提供的大硬盘、大内存服务器很多人很喜欢。TheServerStore自1994年以来,它是一家成熟的企业 IT 设备供应商,专门从事二手服务器和工作站业务,在德克萨斯州拥有40,000 平方英尺的仓库,库存中始终有数千台...

ipage为你推荐
电信主机租用电信服务器租用哪家有实力?英文域名中文域名与英文域名区别免费国外空间哪些免费的国外空间最好?速度快.功能大?网站服务器租用网站服务器租用台湾vps哪个地区的VPS从大陆访问快呢。成都虚拟空间成都市规划信息技术中心如何?apache虚拟主机如何用Apache配置安全虚拟主机 - PHP进阶讨论大连虚拟主机上海未星网络科技有限公司是一家什么样的公司?asp虚拟主机ASP源码上传到虚拟主机什么地方虚拟主机管理软件虚拟主机用什么管理软件,我准备购买一个vps 先咨询下。
网络服务器租用 长沙域名注册 域名备案流程 快速域名备案 西安服务器 google电话 国外主机 sockscap 建站代码 国外免费全能空间 jsp空间 工信部icp备案号 如何用qq邮箱发邮件 爱奇艺vip免费领取 银盘服务 联通网站 智能dns解析 数据库空间 免费php空间 大化网 更多