??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲第一视频在线观看免费,亚洲六月丁香六月婷婷蜜芽,亚洲视频欧洲视频http://www.tkk7.com/pandawang/category/6832.htmlzh-cnThu, 17 May 2007 15:40:59 GMTThu, 17 May 2007 15:40:59 GMT60JFace的作为Java Application使用http://www.tkk7.com/pandawang/archive/2007/05/17/118079.htmlLong Long AgoLong Long AgoThu, 17 May 2007 06:33:00 GMThttp://www.tkk7.com/pandawang/archive/2007/05/17/118079.htmlhttp://www.tkk7.com/pandawang/comments/118079.htmlhttp://www.tkk7.com/pandawang/archive/2007/05/17/118079.html#Feedback0http://www.tkk7.com/pandawang/comments/commentRss/118079.htmlhttp://www.tkk7.com/pandawang/services/trackbacks/118079.htmlException in thread "main" java.lang.NoClassDefFoundError: org/eclipse/core/runtime/IStatus 错误Q虽然已l添加了org.eclipse.jface,org.eclipse.core.runtime,org.eclipse.osgi包,但仍然出错,后来发现org.eclipse.core.runtime.IStatus是在org.eclipse.equonix.common包中Q添加后发现 Q还需要添加org.eclipse.core.command包,再添加后搞定?br>

Long Long Ago 2007-05-17 14:33 发表评论
]]>
SWT中的模式和非模式船体Qmodal or non-modalQ?/title><link>http://www.tkk7.com/pandawang/archive/2007/05/17/118075.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Thu, 17 May 2007 06:27:00 GMT</pubDate><guid>http://www.tkk7.com/pandawang/archive/2007/05/17/118075.html</guid><wfw:comment>http://www.tkk7.com/pandawang/comments/118075.html</wfw:comment><comments>http://www.tkk7.com/pandawang/archive/2007/05/17/118075.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/pandawang/comments/commentRss/118075.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/pandawang/services/trackbacks/118075.html</trackback:ping><description><![CDATA[    以前实现SWT中的模式和非模式H体Qmodal or non-modal window )是通过在子H体中是否截取父H体的消息@环来实现的,现在发现q样好像不行了,但可以通过指定子窗体的样式QstyleQ来制定子窗体是否是模式H体?br>Shell child = new Shell(shell,SWT.SHELL_TRIM|SWT.APPLICATION_MODAL); <br>上面的语句指定了子窗体child为模式窗体。在上面的style中指定SWT.SHELL_TRIM 是ؓ了显C窗体的三个默认按钮Q最大,最和关闭Q,也可以用SWT.DIALOG_TRIMQ不q此时ؓ对话框样式,只有一个默认按钮(关闭Q。默认的Shell是非模式H体Qƈ且是有默认系l按钮的Q即样式为:SWT.SHELL_TRIM|SWT.MODELESS?br>Z说一下,在JFace的Dialog中用模式对话框只要单的讄该对话框setBlockOnOpen(true)卛_?strong><a name="exdialog"></a> <img src ="http://www.tkk7.com/pandawang/aggbug/118075.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/pandawang/" target="_blank">Long Long Ago</a> 2007-05-17 14:27 <a href="http://www.tkk7.com/pandawang/archive/2007/05/17/118075.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eclipse的新功能——tabbed property 的?/title><link>http://www.tkk7.com/pandawang/archive/2006/09/17/70163.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Sun, 17 Sep 2006 14:24:00 GMT</pubDate><guid>http://www.tkk7.com/pandawang/archive/2006/09/17/70163.html</guid><wfw:comment>http://www.tkk7.com/pandawang/comments/70163.html</wfw:comment><comments>http://www.tkk7.com/pandawang/archive/2006/09/17/70163.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/pandawang/comments/commentRss/70163.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/pandawang/services/trackbacks/70163.html</trackback:ping><description><![CDATA[ <p>       Tabbed Property是eclipse3.2中新加入一个view,可以使属性编辑器的功能近乎无限的扩大。这里说明一些Tabbed Property的用方法。Tabbed Property中分成三个部分,Contributer,Tabs,Sections,一个Contributor包含若干个TabsQ一个Tabs又可以包含若q个sections。下面我们来分别q行描述?br />      1。Contributor q需要扩?font face="Courier New">org.eclipse.ui.views.properties.tabbed.PropertyContributor扩展点,定义Ӟ最重要的是定义contributIdQ这个id必须是全局唯一的,q样在加载属性页Ӟ才能扑ֈq个我们定义的属性页Q一般地Q我们都对应于q个属性页的workbenchpart的id作ؓ本contributor的idQ这h们在代码中可以不编码本id字符Ԍ而用getSiteQ).getIdQ)可以得到这个id了(当然Q这样定义id不是必须的)。一个property view可以被多个workbench part׃nQ但 一个workbench part只能有一个property viewQ这个workbench part需要实现ITabbedPropertySheetPageContributor 接口Q这个接口只有一个方法,要求q回本part对应的tabbed property Contributor idQ一般只要return getSiteQ).getIdQ)Q?br />   contributor有如下几个attributeQ?br />   1QtypeMapperQ这个类需要实现org.eclipse.ui.views.properties.tabbed.ITypeMapperQ主要是实现cd的映,因ؓ我们选择的元素ƈ不一定是实现IPropertySource的元素(卌够给property view提供内容的元素)Q比如在GEF中,我们选择的finger实际上是选择了对应的EditPartQ而实际上实现了IPropertySource一般的是model部分的元素,所以这时候我们要Editpart映射到对应的model元素?br />   2QlabelProviderQ需要一个实现org.eclipse.jface.viewers.ILabelProvider的类Q主要是在各个tabs的最上面昄文字和图片?br />   3QpropertyCategoryQ用于聚合多个tabsQ注意至要定义一个categoryQ来聚合tabsQ否则,可能会显Cpropertyp|?/font></p> <p> <font face="Courier New">   2。TabsQ这个需要扩展org.eclipse.ui.views.properties.tabbed.propertyTabs扩展点,其中contributorId是与之相关联的Contributor的idQ然后我们可以定义多个tabQ这些tab的属性如下:<br />   1QlabelQ用于显C在property view的tab bar上的?br />   2QcategoryQ填入的是在Contributor扩展点中定义的那些categoryQ用于聚合tabs<br />   3QidQ本tab的唯一标识<br />   4QafterTabQ用于tab之间的排序,如果q是W一个tabQ则没有afterTabQafterTab指的是在本tab之前的那个tabQƈ且afterTab描述的是在同一个category中的tabsQ不同category之间的顺序是按照在contributor中定义category的顺序来定义的?br />   5QindentedQ如果ؓtureQ则各个tabs是有~进?br />   6QimageQ本tab的图?br /><br />   3。section Q需要扩?org.eclipse.ui.views.properties.tabbed.PropertySections扩展点,它的contributionId是本section所在的Contribution的idQ针Ҏ个tabQ我们可以定义多个sectionQ每个section的attribut描述如下Q?br />   1QidQ本secation的唯一标识<br />   2QtabQ本section所属tab的标?br />   3QclassQ实Corg.eclipse.ui.views.properties.tabbed.AbstractPropertySection抽象cȝc,用于描述q个section的控件和布局?br />   4Qaftersection和上面的aftertab差不多,描述的是同一个tab中的section的顺序,注意afterserction描述的是本section之前的section的id<br />   5QfilterQ一个实现org.eclipse.jface.viewers.IFilter接口的过滤器Q对选中元素q行qo?br />   6QenableForQ一个用于只是选择数目的|必须要符合这个舒服才能能这个section。如果不W合Q则q个sectionpqo了,如果省略本|则section的能器׃会工作了。这是一个自然数Q比如,当enableForQ?Ӟ仅仅只有一个元素被选择的时候,本section才会被能?br /><br />some notesQ?br />    上面说过实现ITabbedPropertySheetPageContributor接口的workbench part除了要实现getContributeIdҎ外,q需要重载getAdapterҎQ因为eclipse的默认加载的property veiw时原来的那个viewQؓ了tabbed property view能够加蝲Q我们就需要重载getAdapterҎQ返回一个TabbedPropertySheetPage对象?br /><br />    在实现section class的时候需要注意,createcontrol旉先应该先创徏一个compositeQ一般是 Composite composite = getWidgetFactory().createFlatFormComposite(parent); 然后各个控g在这个composite上创建?/font> <font face="Courier New"> </font> </p> <p> <br /> </p> <img src ="http://www.tkk7.com/pandawang/aggbug/70163.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/pandawang/" target="_blank">Long Long Ago</a> 2006-09-17 22:24 <a href="http://www.tkk7.com/pandawang/archive/2006/09/17/70163.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eclipse下java动态编译时com.sun.tools.javac.Maincd载问题的解决http://www.tkk7.com/pandawang/archive/2006/08/20/64639.htmlLong Long AgoLong Long AgoSun, 20 Aug 2006 09:28:00 GMThttp://www.tkk7.com/pandawang/archive/2006/08/20/64639.htmlhttp://www.tkk7.com/pandawang/comments/64639.htmlhttp://www.tkk7.com/pandawang/archive/2006/08/20/64639.html#Feedback0http://www.tkk7.com/pandawang/comments/commentRss/64639.htmlhttp://www.tkk7.com/pandawang/services/trackbacks/64639.html

理解Java ClassLoader机制

Java ClassLoader

2006-5-23
java.lang.NoClassDefFoundError: com/sun/tools/javac/Main
最q在使用java的动态编译的时候出现的问题,主要是由于在使用ccom.sun.tool.javac.Main?L出现NoClassDefFoundError的错?后来扑ֈ如下的文?分析,可能是由于对于包tools.jar的加载问?虽然我在classpath中声明了q个?但在eclipse环境?始终都还是出现运行时异常,对于~译时正?q行时异常的情况,eclipse一般都是由于其自n的加载机刉成?在eclipse?对于一般的java工程,只要讄了系l的classpath,在其中添加了tools.jar?卛_;对于plugin工程,我是tools.jar?直接拯到本工程?q在property中引?而且在META-INF/MANIFEST.MF文g中的Runtime늚classpath中添加了q个tool.jar?q样在运行时没有异怺,可以正常~译?
当JVMQJava虚拟机)启动Ӟ会Ş成由三个cd载器l成的初始类加蝲器层ơ结构:

       bootstrap classloader
                |
       extension classloader
                |
       system classloader

bootstrap classloader Q引|也称为原始)cd载器Q它负责加蝲Java的核心类。在Sun的JVM中,在执行java的命令中使用-Xbootclasspath选项或? D选项指定sun.boot.class.pathpȝ属性值可以指定附加的cR这个加载器的是非常Ҏ的,它实际上不是 java.lang.ClassLoader的子c,而是由JVM自n实现的。大家可以通过执行以下代码来获得bootstrap classloader加蝲了那些核心类库:
   URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();
   for (int i = 0; i < urls.length; i++) {
     System.out.println(urls.toExternalform());
   }
在我的计机上的l果为:
文g:/C:/j2sdk1.4.1_01/jre/lib/endorsed/dom.jar
文g:/C:/j2sdk1.4.1_01/jre/lib/endorsed/sax.jar
文g:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xalan-2.3.1.jar
文g:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xercesImpl-2.0.0.jar
文g:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xml-apis.jar
文g:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xsltc.jar
文g:/C:/j2sdk1.4.1_01/jre/lib/rt.jar
文g:/C:/j2sdk1.4.1_01/jre/lib/i18n.jar
文g:/C:/j2sdk1.4.1_01/jre/lib/sunrsasign.jar
文g:/C:/j2sdk1.4.1_01/jre/lib/jsse.jar
文g:/C:/j2sdk1.4.1_01/jre/lib/jce.jar
文g:/C:/j2sdk1.4.1_01/jre/lib/charsets.jar
文g:/C:/j2sdk1.4.1_01/jre/classes
q时大家知道了ؓ什么我们不需要在pȝ属性CLASSPATH中指定这些类库了吧,因ؓJVM在启动的时候就自动加蝲它们了?br />
extension classloader Q扩展类加蝲器,它负责加载JRE的扩展目录(JAVA_HOME/jre/lib/ext或者由java.ext.dirspȝ属性指定的Q中JAR的类包。这为引入除Java核心cM外的新功能提供了一个标准机制。因为默认的扩展目录Ҏ有从同一个JRE中启动的JVM都是通用的,所以放入这个目录的 JARcdҎ有的JVM和system classloader都是可见的。在q个实例上调用方法getParent()Lq回I值nullQ因为引导加载器bootstrap classloader不是一个真正的ClassLoader实例。所以当大家执行以下代码Ӟ
   System.out.println(System.getProperty("java.ext.dirs"));
   ClassLoader extensionClassloader=ClassLoader.getSystemClassLoader().getParent();
   System.out.println("the parent of extension classloader : "+extensionClassloader.getParent());
l果为:
C:\j2sdk1.4.1_01\jre\lib\ext
the parent of extension classloader : null
extension classloader是system classloader的parentQ而bootstrap classloader是extension classloader的parentQ但它不是一个实际的classloaderQ所以ؓnull?br />
system classloader Q系l(也称为应用)cd载器Q它负责在JVM被启动时Q加载来自在命ojava中的-classpath或者java.class.pathpȝ属性或?CLASSPATH操作pȝ属性所指定的JARcd和类路径。总能通过静态方法ClassLoader.getSystemClassLoader()扑ֈ该类加蝲器。如果没有特别指定,则用戯定义的Q何类加蝲器都该cd载器作ؓ它的父加载器。执行以下代码即可获得:
   System.out.println(System.getProperty("java.class.path"));
输出l果则ؓ用户在系l属性里面设|的CLASSPATH?br />classloader 加蝲cȝ的是全盘负责委托机制。所谓全盘负责,x当一个classloader加蝲一个Class的时候,q个Class所依赖的和引用的所?Class也由q个classloader负责载入Q除非是昑ּ的用另外一个classloader载入Q委托机制则是先让parentQ父Q类加蝲?(而不是superQ它与parent classloadercM是承关p?LQ只有在parent找不到的时候才从自qc\径中d找。此外类加蝲q采用了cache机制Q也是如果 cache中保存了q个Classq接返回它Q如果没有才从文件中d和{换成ClassQƈ存入cacheQ这是Z么我们修改了Class但是必须重新启动JVM才能生效的原因?br />

每个ClassLoader加蝲Class的过E是Q?br />1.此Class是否载入q(卛_cache中是否有此ClassQ,如果有到8,如果没有?
2.如果parent classloader不存在(没有parentQ那parent一定是bootstrap classloader了)Q到4
3.hparent classloader载入Q如果成功到8Q不成功?
4.hjvm从bootstrap classloader中蝲入,如果成功?
5.LClass文gQ从与此classloader相关的类路径中寻找)。如果找不到则到7.
6.从文件中载入ClassQ到8.
7.抛出ClassNotFoundException.
8.q回Class.

其中5.6步我们可以通过覆盖ClassLoader的findClassҎ来实现自q载入{略。甚臌盖loadClassҎ来实现自q载入q程?br />
cd载器的顺序是Q?br />先是bootstrap classloaderQ然后是extension classloaderQ最后才是system classloader。大家会发现加蝲的Class是重要的越在靠前面。这样做的原因是Z安全性的考虑Q试惛_果system classloader“亲自”加载了一个具有破坏性的“java.lang.System”类的后果吧。这U委托机制保证了用户即h一个这Lc,也把它加入到了类路径中,但是它永q不会被载入Q因个类L由bootstrap classloader来加载的。大家可以执行一下以下的代码Q?br />   System.out.println(System.class.getClassLoader());
会看到l果是nullQ这p明java.lang.System是由bootstrap classloader加蝲的,因ؓbootstrap classloader不是一个真正的ClassLoader实例Q而是由JVM实现的,正如前面已经说过的?br />
下面p我们来看看JVM是如何来为我们来建立cd载器的结构的Q?br />sun.misc.LauncherQ顾名思义Q当你执行java命o的时候,JVM会先使用bootstrap classloader载入q初始化一个LauncherQ执行下来代码:
  System.out.println("the Launcher's classloader is "+sun.misc.Launcher.getLauncher().getClass().getClassLoader());
l果为:
  the Launcher's classloader is null (因ؓ是用bootstrap classloader加蝲,所以class loader为null)
Launcher 会根据系l和命o讑֮初始化好class loaderl构QJVMq它来获得extension classloader和system classloader,q蝲入所有的需要蝲入的ClassQ最后执行java命o指定的带有静态的mainҎ的Class。extension classloader实际上是sun.misc.Launcher$ExtClassLoadercȝ一个实例,system classloader实际上是sun.misc.Launcher$AppClassLoadercȝ一个实例。ƈ且都?java.net.URLClassLoader的子cR?br />
让我们来看看Launcher初试化的q程的部分代码?br />
Launcher的部分代码:
public class Launcher  {
   public Launcher() {
       ExtClassLoader extclassloader;
       try {
           //初始化extension classloader
           extclassloader = ExtClassLoader.getExtClassLoader();
       } catch(IOException ioexception) {
           throw new InternalError("Could not create extension class loader");
       }
       try {
           //初始化system classloaderQparent是extension classloader
           loader = AppClassLoader.getAppClassLoader(extclassloader);
       } catch(IOException ioexception1) {
           throw new InternalError("Could not create application class loader");
       }
       //system classloader讄成当前线E的context classloaderQ将在后面加以介l)
       Thread.currentThread().setContextClassLoader(loader);
       ......
   }
   public ClassLoader getClassLoader() {
       //q回system classloader
       return loader;
   }
}

extension classloader的部分代码:
static class Launcher$ExtClassLoader extends URLClassLoader {

   public static Launcher$ExtClassLoader getExtClassLoader()
       throws IOException
   {
       File afile[] = getExtDirs();
       return (Launcher$ExtClassLoader)AccessController.doPrivileged(new Launcher$1(afile));
   }
  private static File[] getExtDirs() {
       //获得pȝ属性“java.ext.dirs?br />       String s = System.getProperty("java.ext.dirs");
       File afile[];
       if(s != null) {
           StringTokenizer stringtokenizer = new StringTokenizer(s, File.pathSeparator);
           int i = stringtokenizer.countTokens();
           afile = new File;
           for(int j = 0; j < i; j++)
               afile[j] = new File(stringtokenizer.nextToken());

       } else {
           afile = new File[0];
       }
       return afile;
   }
}

system classloader的部分代码:
static class Launcher$AppClassLoader extends URLClassLoader
{

   public static ClassLoader getAppClassLoader(ClassLoader classloader)
       throws IOException
   {
       //获得pȝ属性“java.class.path?br />       String s = System.getProperty("java.class.path");
       File afile[] = s != null ? Launcher.access$200(s) : new File[0];
       return (Launcher$AppClassLoader)AccessController.doPrivileged(new Launcher$2(s, afile, classloader));
   }
}

看了源代码大家就清楚了吧Qextension classloader是用系l属性“java.ext.dirs”设|类搜烦路径的,q且没有parent。system classloader是用系l属性“java.class.path”设|类搜烦路径的,q且有一个parent classloader。Launcher初始化extension classloaderQsystem classloaderQƈsystem classloader讄成ؓcontext classloaderQ但是仅仅返回system classloaderlJVM?br />
  q里怎么又出来一个context classloader呢?它有什么用呢?我们在徏立一个线EThread的时候,可以个线E通过setContextClassLoaderҎ来指定一个合适的classloader作ؓq个U程的context classloaderQ当此线E运行的时候,我们可以通过getContextClassLoaderҎ来获得此context classloaderQ就可以用它来蝲入我们所需要的Class。默认的是system classloader。利用这个特性,我们可以“打破”classloader委托机制了,父classloader可以获得当前U程的context classloaderQ而这个context classloader可以是它的子classloader或者其他的classloaderQ那么父classloader可以从其获得所需?ClassQ这打破了只能向父classloaderh的限制了。这个机制可以满_我们的classpath是在q行时才定,q由定制?classloader加蝲的时?由system classloader(卛_jvm classpath?加蝲的class可以通过context classloader获得定制的classloaderq加载入特定的class(通常是抽象类和接?定制的classloader中是其实?,例如web应用中的servlet是用这U机制加载的.


好了Q现在我们了解了classloader的结构和工作原理Q那么我们如何实现在q行时的动态蝲入和更新呢?只要我们能够动态改变类搜烦路径和清除classloader的cache中已l蝲入的Classp了,有两个方案,一是我们承一个classloaderQ覆盖loadclassҎQ动态的LClass文gq用defineClassҎ来;另一个则非常单实用,只要重新使用一个新的类搜烦路径来new一个classloaderp了,q样xCcL索\径以便来载入新的ClassQ也重新生成了一个空白的cache(当然,cL索\径不一定必L?。噢Q太好了Q我们几乎不用做什么工作,java.netURLClassLoader正是一个符合我们要求的classloaderQ我们可以直接用或者承它可以了Q?br />
q是j2se1.4 API的doc中URLClassLoader的两个构造器的描qͼ
URLClassLoader(URL[] urls)
         Constructs a new URLClassLoader for the specified URLs using the default delegation parent ClassLoader.
URLClassLoader(URL[] urls, ClassLoader parent)
         Constructs a new URLClassLoader for the given URLs.
其中URL[] urls是我们要设|的cL索\径,parent是q个classloader的parent classloaderQ默认的是system classloader?br />

好,现在我们能够动态的载入Class了,q样我们可以利用newInstanceҎ来获得一个Object。但我们如何此Object造型呢?可以此Object造型成它本n的Class吗?

首先让我们来分析一下java源文件的~译Q运行吧Qjavac命o是调用“JAVA_HOME/lib/tools.jar”中的“com.sun.tools.javac.Main”的compileҎ来编译:

   public static int compile(String as[]);

   public static int compile(String as[], PrintWriter printwriter);

q回0表示~译成功Q字W串数组as则是我们用javac命o~译时的参数Q以I格划分。例如:
javac -classpath c:\foo\bar.jar;. -d c:\ c:\Some.java
则字W串数组as为{"-classpath","c:\\foo\\bar.jar;.","-d","c:\\","c:\\Some.java"}Q如果带有PrintWriter参数Q则会把~译信息出到q个指定的printWriter中。默认的输出是System.err?br />
其中 Main是由JVM使用Launcher初始化的system classloader载入的,Ҏ全盘负责原则Q编译器在解析这个java源文件时所发现的它所依赖和引用的所有Class也将由system classloader载入Q如果system classloader不能载入某个ClassӞ~译器将抛出一个“cannot resolve symbol”错误?br />
所以首先编译就通不q,也就是编译器无法~译一个引用了不在CLASSPATH中的未知Class的java源文Ӟ而由于拼写错误或者没有把所需cd攑ֈCLASSPATH中,大家一定经常看到这个“cannot resolve symbol”这个编译错误吧Q?br />
其次Q就是我们把q个Class攑ֈ~译路径中,成功的进行了~译Q然后在q行的时候不把它攑օ到CLASSPATH中而利用我们自q classloader来动态蝲入这个ClassQ这时候也会出现“java.lang.NoClassDefFoundError”的q例Qؓ什么呢Q?br />
我们再来分析一下,首先调用q个造型语句的可执行的Class一定是由JVM使用Launcher初始化的system classloader载入的,Ҏ全盘负责原则Q当我们q行造型的时候,JVM也会使用system classloader来尝试蝲入这个Class来对实例q行造型Q自然在system classloaderL不到q个Class时就会抛出“java.lang.NoClassDefFoundError”的q例?br />
OKQ现在让我们来ȝ一下,java文g的编译和Class的蝲入执行,都是使用Launcher初始化的system classloader作ؓc蝲入器的,我们无法动态的改变system classloaderQ更无法让JVM使用我们自己的classloader来替换system classloaderQ根据全盘负责原则,限制了~译和运行时Q我们无法直接显式的使用一个system classloaderL不到的ClassQ即我们只能使用Java核心cdQ扩展类库和CLASSPATH中的cd中的Class?br />
q不dQ再试一下这U情况,我们把这个Class也放入到CLASSPATH中,让system classloader能够识别和蝲入。然后我们通过自己的classloader来从指定的class文g中蝲入这个ClassQ不能够委托 parent载入Q因样会被system classloader从CLASSPATH中将其蝲入)Q然后实例化一个ObjectQƈ造型成这个ClassQ这样JVM也识别这个ClassQ因?system classloader能够定位和蝲入这个Class从CLASSPATH中)Q蝲入的也不是CLASSPATH中的q个ClassQ而是?CLASSPATH外动态蝲入的Q这h行了吧Q十分不q的是,q时会出现“java.lang.ClassCastException”违例?br />
Z么呢Q我们也来分析一下,不错Q我们虽然从CLASSPATH外用我们自qclassloader动态蝲入了q个ClassQ但它的实例造型的时候是JVM会用system classloader来再ơ蝲入这个ClassQƈ试用我们的自己的classloader载入的Class的一个实例造型为system classloader载入的这个ClassQ另外的一个)。大家发C么问题了吗?也就是我们尝试将从一个classloader载入的Class的一个实例造型为另外一个classloader载入的ClassQ虽然这两个Class的名字一P甚至是从同一个class文g中蝲入。但不幸的是JVM 却认个两个Class是不同的Q即JVM认ؓ不同的classloader载入的相同的名字的ClassQ即使是从同一个class文g中蝲入的Q是不同的!q样做的原因我想大概也是主要Z安全性考虑Q这样就保证所有的核心Javac都是system classloader载入的,我们无法用自qclassloader载入的相同名字的Class的实例来替换它们的实例?br />
看到q里Q聪明的读者一定想C该如何动态蝲入我们的ClassQ实例化Q造型q调用了吧!

那就是利用面向对象的基本Ҏ之一的多形性。我们把我们动态蝲入的Class的实例造型成它的一个system classloader所能识别的父类p了!q是Z么呢Q我们还是要再来分析一ơ。当我们用我们自qclassloader来动态蝲入这我们只要把这个Class的时候,发现它有一个父cClassQ在载入它之前JVM先会载入q个父类ClassQ这个父cClass是system classloader所能识别的Q根据委托机Ӟ它将由system classloader载入Q然后我们的classloader再蝲入这个ClassQ创Z个实例,造型个父cClassQ注意了Q造型成这个父c?Class的时候(也就是上溯)是面向对象的java语言所允许的ƈ且JVM也支持的QJVM׃用system classloader再次载入q个父类ClassQ然后将此实例造型个父cClass。大家可以从q个q程发现q个父类Class都是?system classloader载入的,也就是同一个class loader载入的同一个ClassQ所以造型的时候不会出CQ何异常。而根据多形性,调用q个父类的方法时Q真正执行的是这个ClassQ非父类 ClassQ的覆盖了父cL法的Ҏ。这些方法中也可以引用system classloader不能识别的ClassQ因为根据全盘负责原则,只要载入q个Class的classloaderx们自己定义的 classloader能够定位和蝲入这些Classp了?br />
q样我们可以事先定义好一l接口或者基cdƈ攑օCLASSPATH中,然后在执行的时候动态的载入实现或者承了q些接口或基cȝ子类。还不明白吗Q让我们来想一想Servlet吧,web application server能够载入Ml承了Servlet的Classq正的执行它们Q不它实际的Class是什么,是都把它们实例化成Z个Servlet ClassQ然后执行Servlet的initQdoPostQdoGet和destroy{方法的,而不这个Servlet是从web- inf/lib和web-inf/classes下由system classloader的子classloader(卛_制的classloader)动态蝲入。说了这么多希望大家都明白了。在applet,ejb{容器中,都是采用了这U机?

对于以上各种情况Q希望大家实际编写一些example来实验一下?br />
最后我再说点别的, classloader虽然UCؓcd载器Q但q不意味着只能用来加蝲ClassQ我们还可以利用它也获得囄Q音频文件等资源的URLQ当Ӟq些资源必须在CLASSPATH中的jarcd中或目录下。我们来看API的doc中关于ClassLoader的两个寻找资源和Class的方法描q吧Q?br />        public URL getResource(String name)
        用指定的名字来查找资源,一个资源是一些能够被class代码讉K的在某种E度上依赖于代码位置的数据(囄Q音频,文本{等Q?br />               一个资源的名字是以'/'号分隔确定资源的路径名的?br />               q个Ҏ先hparent classloader搜烦资源Q如果没有parentQ则会在内置在虚拟机中的classloaderQ即bootstrap classloaderQ的路径中搜索。如果失败,q个Ҏ调用findResource(String)来寻找资源?br />        public static URL getSystemResource(String name)
               从用来蝲入类的搜索\径中查找一个指定名字的资源。这个方法用system class loader来定位资源。即相当于ClassLoader.getSystemClassLoader().getResource(name)?br />
例如Q?br />   System.out.println(ClassLoader.getSystemResource("java/lang/String.class"));
的结果ؓQ?br />   jar:文g:/C:/j2sdk1.4.1_01/jre/lib/rt.jar!/java/lang/String.class
表明String.class文g在rt.jar的java/lang目录中?br />因此我们可以图片等资源随同Class一同打包到jarcd中(当然Q也可单独打包这些资源)q添加它们到class loader的搜索\径中Q我们就可以无需兛_q些资源的具体位|,让class loader来帮我们L了!


Long Long Ago 2006-08-20 17:28 发表评论
]]>
ZRCP的GEF~辑器中RetargetAction的注册问?/title><link>http://www.tkk7.com/pandawang/archive/2006/08/19/64532.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Sat, 19 Aug 2006 09:35:00 GMT</pubDate><guid>http://www.tkk7.com/pandawang/archive/2006/08/19/64532.html</guid><wfw:comment>http://www.tkk7.com/pandawang/comments/64532.html</wfw:comment><comments>http://www.tkk7.com/pandawang/archive/2006/08/19/64532.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/pandawang/comments/commentRss/64532.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/pandawang/services/trackbacks/64532.html</trackback:ping><description><![CDATA[最q做的gef~辑器在删除旉C一些问?是不能通过delete键删?到处搜集资料,解决?<br />首先需要在相应rcp工程中的ActionBarAdvisercM注册相应的Action,比如对应于deleteAction,我在Ҏorg.eclipse.ui.application.ActionBarAdvisor#makeAction(IWorkbenchWindow)中注册deleteAction,如下:<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_56_144_Open_Image" onclick="this.style.display='none'; Codehighlighter1_56_144_Open_Text.style.display='none'; Codehighlighter1_56_144_Closed_Image.style.display='inline'; Codehighlighter1_56_144_Closed_Text.style.display='inline';" src="http://www.tkk7.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_56_144_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_56_144_Closed_Text.style.display='none'; Codehighlighter1_56_144_Open_Image.style.display='inline'; Codehighlighter1_56_144_Open_Text.style.display='inline';" src="http://www.tkk7.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> makeAction(</span><span style="COLOR: #0000ff">final</span><span style="COLOR: #000000"> IWorkbenchWindow window)</span><span id="Codehighlighter1_56_144_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/images/dot.gif" /></span><span id="Codehighlighter1_56_144_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    IAction delAction </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> ActionFactory.DELETE.create(window);<br /><img src="http://www.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    register(delAction);<br /><img src="http://www.tkk7.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /><img src="http://www.tkk7.com/images/OutliningIndicators/None.gif" align="top" /></span></div><br />只是q么讄q是不能删除相应的图形元?需要在相应的编辑器中重载initҎ,d如下的代?br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_80_378_Open_Image" onclick="this.style.display='none'; Codehighlighter1_80_378_Open_Text.style.display='none'; Codehighlighter1_80_378_Closed_Image.style.display='inline'; Codehighlighter1_80_378_Closed_Text.style.display='inline';" src="http://www.tkk7.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_80_378_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_80_378_Closed_Text.style.display='none'; Codehighlighter1_80_378_Open_Image.style.display='inline'; Codehighlighter1_80_378_Open_Text.style.display='inline';" src="http://www.tkk7.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> init(IEditorSite site, IEditorInput input) </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> PartInitException </span><span id="Codehighlighter1_80_378_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/images/dot.gif" /></span><span id="Codehighlighter1_80_378_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> TODO Auto-generated method stub</span><span style="COLOR: #008000"><br /><img src="http://www.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">super</span><span style="COLOR: #000000">.init(site, input);<br /><img src="http://www.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    ActionRegistry registry </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> getActionRegistry();<br /><img src="http://www.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    IActionBars bar </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> site.getActionBars();<br /><img src="http://www.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    String id </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> ActionFactory.DELETE.getId();<br /><img src="http://www.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    bar.setGlobalActionHandler(id,registry.getAction(id));<br /><img src="http://www.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    bar.updateActionBars();<br /><img src="http://www.tkk7.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div><br />在这里仔l研I会发现,在第一D代码中实际上时创徏了一个action,q是一个RetargetAction,而在super.init()Ҏ会调用一个createActionҎ,q里创徏的是gef默认的redoAction undoAction selectionAction deleteAction saveAction.需要注意的是RetargetAction是一U可以跟t当前活动的部分,׃retargetAction含有一个id,如果q个zd部分提供的handler的id和retargetAction的id相同,那么相应的对retargetAction的调用就转嫁成对当前q个zd部分的handle的调?(当然如果Ҏ没有handle,那么q个action会disable).所?我们可以看出?q个retargetAction会在gef~辑器激zd调用gef的deleteAction.<img src ="http://www.tkk7.com/pandawang/aggbug/64532.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/pandawang/" target="_blank">Long Long Ago</a> 2006-08-19 17:35 <a href="http://www.tkk7.com/pandawang/archive/2006/08/19/64532.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转蝲][备䆾][Java|Eclipse|GEF]Figure是如何定位和讄大小Q?http://www.tkk7.com/pandawang/archive/2006/08/14/63424.htmlLong Long AgoLong Long AgoMon, 14 Aug 2006 03:18:00 GMThttp://www.tkk7.com/pandawang/archive/2006/08/14/63424.htmlhttp://www.tkk7.com/pandawang/comments/63424.htmlhttp://www.tkk7.com/pandawang/archive/2006/08/14/63424.html#Feedback0http://www.tkk7.com/pandawang/comments/commentRss/63424.htmlhttp://www.tkk7.com/pandawang/services/trackbacks/63424.html http://www.approc.com/

[Java|Eclipse|GEF]Figure是如何定位和讄大小Q?

有两U会创徏囑օQ?br />1、打开囑Ş文gӞ先会创徏所有的modelQ这样图元的定位和设|大是依据囑օmodel的size和location属性,通过囑օEditPart.refreshVisuals()来设|的
2、通过拖放托盘里面的图标来建立的图元,会先讄model的sizeQ然后通过model对应的figure.setPreferredSize()来设|了Q而location则是通过鼠标的位|来定?/div>


Long Long Ago 2006-08-14 11:18 发表评论
]]>[转蝲][备䆾][Java|Eclipse]用NLS的方式访问资源文?http://www.tkk7.com/pandawang/archive/2006/08/14/63423.htmlLong Long AgoLong Long AgoMon, 14 Aug 2006 03:16:00 GMThttp://www.tkk7.com/pandawang/archive/2006/08/14/63423.htmlhttp://www.tkk7.com/pandawang/comments/63423.htmlhttp://www.tkk7.com/pandawang/archive/2006/08/14/63423.html#Feedback0http://www.tkk7.com/pandawang/comments/commentRss/63423.htmlhttp://www.tkk7.com/pandawang/services/trackbacks/63423.html
http://www.approc.com/
现在?.1里面讉K资源文g变得比较单了Q用户可以通过l承osgi.util.NLSQ典型例子:
public class MsgBoundle extends NLS{
      
private final static String BOUNDLE_NAME 
                       
= "resource.msg";
      
public static String mo_1;
      
public static String mo_2;

      
static{
         NLS.initializeMessage(BOUNDLE_NAME,
                       MsgBoundle.
class);
      }

}


好啦Q现在就可以建立资源文g了,文g应该建在哪里呢?跟踪代码发现Q这个由BOUNDLE_NAME军_Q在MessageResourceBoundle.buildVariants()中,会将BOUNDLE_NAME中的?"替换?/"Q然后再Ҏ地区讑֮l合几种不同的资源文件名Uͼ比如我的是:

1、resource/msg_zh_CN.properties
2、resource/msg_zh.properties
3、resource/msg.properties
注意Q这三个文g是有序的哦

然后通过EclipseClassLoader.getResource()?a onclick="return false;" href="javascript:void(0);">查找q些文gQƈ文件中的D予给MsgBoundle对应的成员变量?img src ="http://www.tkk7.com/pandawang/aggbug/63423.html" width = "1" height = "1" />

Long Long Ago 2006-08-14 11:16 发表评论
]]>
Linux下引入Plugin-Project的一个问?/title><link>http://www.tkk7.com/pandawang/archive/2006/07/19/58924.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Wed, 19 Jul 2006 02:26:00 GMT</pubDate><guid>http://www.tkk7.com/pandawang/archive/2006/07/19/58924.html</guid><wfw:comment>http://www.tkk7.com/pandawang/comments/58924.html</wfw:comment><comments>http://www.tkk7.com/pandawang/archive/2006/07/19/58924.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/pandawang/comments/commentRss/58924.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/pandawang/services/trackbacks/58924.html</trackback:ping><description><![CDATA[在linuxQubuntuQ下引入了在windows工作时徏立的一个pluginProjectQ但是发玎ͼ在plugin.xml中require包都没有了,?.0以后q些require都是攑֜MANIFEST.MF文g中的Q这两个文g是同步的Q即在编辑plugin.xml文g视图时会看到MANIFEST.MF文g中的requireQ不q在从windows引入后就看不CQ不q这是发现MANIFEST.MF和他所在的目录META-INF都变成了写Q改成大写后Q再update classpath可以了?br /><img src ="http://www.tkk7.com/pandawang/aggbug/58924.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/pandawang/" target="_blank">Long Long Ago</a> 2006-07-19 10:26 <a href="http://www.tkk7.com/pandawang/archive/2006/07/19/58924.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GEF中鼠标双M件的截获http://www.tkk7.com/pandawang/archive/2006/06/08/51513.htmlLong Long AgoLong Long AgoThu, 08 Jun 2006 14:21:00 GMThttp://www.tkk7.com/pandawang/archive/2006/06/08/51513.htmlhttp://www.tkk7.com/pandawang/comments/51513.htmlhttp://www.tkk7.com/pandawang/archive/2006/06/08/51513.html#Feedback0http://www.tkk7.com/pandawang/comments/commentRss/51513.htmlhttp://www.tkk7.com/pandawang/services/trackbacks/51513.html http://dev.eclipse.org/mhonarc/lists/gef-dev/msg00183.html
Ask:
How to add a double click event or Request on a figure?when double click on a figure, a dialog pop up and do some actions.for example when double click on
a UML class figure, a dialog pop up, user can Add a method to the class.
Answer:
This is already done in GEF. Your editpart will receive a performRequest(req) with the type RequestConstants.REQ_OPEN.
See SelectEditPartTRacker#performOpen()

-randy
是在figure对应的editpart中重载方法performRequest(Request req),q判断req的type是否为RequestConstants.REQ_OPEN,如果?则处理这个双M?
q个Ҏ是个回调Ҏ,在SelectEditPartTRacker#performOpen() 中调用的.


Long Long Ago 2006-06-08 22:21 发表评论
]]>
GEF中容器图形的坐标问题http://www.tkk7.com/pandawang/archive/2006/05/15/46203.htmlLong Long AgoLong Long AgoMon, 15 May 2006 06:04:00 GMThttp://www.tkk7.com/pandawang/archive/2006/05/15/46203.htmlhttp://www.tkk7.com/pandawang/comments/46203.htmlhttp://www.tkk7.com/pandawang/archive/2006/05/15/46203.html#Feedback0http://www.tkk7.com/pandawang/comments/commentRss/46203.htmlhttp://www.tkk7.com/pandawang/services/trackbacks/46203.html

Long Long Ago 2006-05-15 14:04 发表评论
]]>
eclipse中获得插件绝对\径的Ҏhttp://www.tkk7.com/pandawang/archive/2006/05/01/44313.htmlLong Long AgoLong Long AgoMon, 01 May 2006 14:45:00 GMThttp://www.tkk7.com/pandawang/archive/2006/05/01/44313.htmlhttp://www.tkk7.com/pandawang/comments/44313.htmlhttp://www.tkk7.com/pandawang/archive/2006/05/01/44313.html#Feedback0http://www.tkk7.com/pandawang/comments/commentRss/44313.htmlhttp://www.tkk7.com/pandawang/services/trackbacks/44313.html
    /**
     * 得到插g的绝对\?br />     * 
     * 
@return 路径
     
*/

    
public static String getPath() {
        String path;
        
try {
            path 
= FileLocator.toFileURL(
                    Platform.getBundle(pluginId).getEntry(
"")).getPath();
            path 
= path.substring(path.indexOf("/"+ 1, path.length());
        }
 catch (IOException e) {
            path 
= "";
            e.printStackTrace();
        }

        
return path;
    }
其中FileLocator#toFileURL是在3.2中添加的,代替了原来的Platform#asLocalURL,q且对于FileLocator#toFileURL,if the plugin was a jar, it will extract the file into a temporary location


Long Long Ago 2006-05-01 22:45 发表评论
]]>
GEF学习记?/title><link>http://www.tkk7.com/pandawang/archive/2006/04/09/40091.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Sun, 09 Apr 2006 06:38:00 GMT</pubDate><guid>http://www.tkk7.com/pandawang/archive/2006/04/09/40091.html</guid><wfw:comment>http://www.tkk7.com/pandawang/comments/40091.html</wfw:comment><comments>http://www.tkk7.com/pandawang/archive/2006/04/09/40091.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/pandawang/comments/commentRss/40091.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/pandawang/services/trackbacks/40091.html</trackback:ping><description><![CDATA[上文提到的GEF工作q程中还有一些不太详l的地方Q这里做些补充?br />再GEF中UI的操作交互都是通过构徏RequestQƈ调用EditPart中的API来完成相应的操作Q这些API可以分ؓ四类Q?br />1。 ?strong><font face="Courier New">EditPart getTargetEditPart(Request)<br />   boolean understandsRequest(Request)<br /></font></strong>再我们进行交互操作时Q首先要定Ȁzȝ是那个EditPartQ经常是一个当前被选中的viewer和通过单击选择的EditPart的复合体。这个被选择的部仉过询问每个被选择的EditPart是否处理q个requestQ通过understandsRequestҎQ。那个在鼠标单击定的EditPart是通过viewer的帮助和getTargetEditPartҎ来找到的。ƈ不是所有的交互都有target?br />2?br /><strong><font face="Courier New">void showSourceFeedback(Request)<br />void eraseSourceFeedback(Request)<br />void showTargetFeedback(Request)<br />void eraseTargetFeedback(Request)</font></strong><br />在我们的交互操作特别是托拽图形时Q就需要EditPart来回显(FeedbackQ,托拽源被认ؓ是v作用的那个editpartQ目的部件被认ؓ是鼠标的目的地。showXXXFeedback可能是在鼠标Ud目的圎ͼ但未作用于目的part时调用,eraseXXXFeedback则可能是在鼠标作用于目的part后调用的?br />3?strong><font face="Courier New">Command getCommand(Request)</font></strong><br />q个Ҏ用于获得可执行的命o列表Q命令可以对模型q行操作QEditpart通过request询问Editpolicy来获得相应的command列表。同时command也可以判断这个交互操作是否时可能的。如果没有command或者command不能执行Q则ui会指个操作是不能执行的(鼠标变成止操作的样子)。如果一个editpartq回null作ؓcommand则它不会Lq个交互操作Q除非没有一个command被提供。ؓ了指C某个操作是不能执行的则EditPart需要返回一个不能执行的command?br />4?strong><font face="Courier New">void performRequest(Request)</font></strong><br />q有一UAPIQ它让EditPart去do somethingQ可能是一些ƈ不会立即改变model的改变,比如打开对话框或者激zȝ接编辑模式?br /><br />        EditPartq不直接q行~辑Q它操作委托给EditPolicyQ每个EditPolicy专著于一U编辑Q务或者一l相关的操作。当上面的API被调用后Q除了performRequestҎQ,EditPart便委托给它的EditPolicy来处理这个request。对于不同的ҎQEditPart可能是在W一个能处理request的policy处就停止调用了或者每个policy都有Z执行q个request。GEF提供了几个默认的policyQ不q还是需要实现其中的一些特定方法?br /><br />         q里再废话一点,在注册相应的EditPolicyӞ需要指定RoleQ这是一个字W串Q用来标C个EditPolicyQ相同的Role对应的EditPolicy会被替换Q例如子cd以通过Roleq个Key来覆盖其父类所安装的EditPolicy。EditPolicyQRoleQ分成两U类型,一U是囑Ş的,一U是非图形的Q上文中有提刎ͼq里详细的描qC下:<br /><strong>Non-Graphical Roles:</strong><br />1) <strong>COMPONENT_ROLE</strong>: 一个Component存在于一个parent中,q且可以从parent中删除。更Z般的Q它可以使Q何只涉及到这个EditPartQ而与View无关的东ѝ?More generally, it is anything that involves only this EditPart.) <br />2) <strong>CONNECTION_ROLE</strong> q是ConnectionEditParts应该有的一个基本角艌ӀConnections同Components有一点不同,删除Connections旉常q需要其从其source和target节点中删除,而不是从其parent中删除?<br />3) <strong>CONTAINER_ROLE</strong> 大部分拥有children的EditParts都应该具有这个角艌Ӏ一个Container会涉及到adds/orphans以及creates/deletes{操作?<br />4) <strong>NODE_ROLE</strong> 如果一个EditParts用户ConnectionQ则其应该具有这个角Ԍ它可以用来创建,删除Q重新连接一个Connection?<br /><strong>Graphical Roles:</strong><br />1) <strong>PRIMARY_DRAG_ROLE:</strong> 用来允许用户拖动q个EditPart。用户可以通过点击q个EditPart然后拖动Q或者点击这个EditPart所创徏的一个Handle来进行拖动?<br />2) <strong>LAYOUT_ROLE</strong>: Layout角色用来攑֜一个Container的EditPart上,q个EditPart拥有一个graphical layout。如果这个layout有constraintsQ则它需要通过计算来得到这个constraints?<br />3) <strong>GRAPHICAL_NODE_ROLE</strong>: A node supports connections to terminals. When creating and manipulating connections, EditPolicies with this role might analyze a Request's data to perform "hit testing" on the graphical view and determine the semantics of the connection. 用于支持q接到重点的nodeQ当创徏、操作连接时Q包含这个Role的Editpolicy会分析request的数据,来在囑Şview上做“hit testing”,q且判断q个connection的语义?br />4) <strong>CONNECTION_ENDPOINTS_ROLE:</strong> q个Role允许用户拖动一个ConnectionEditPart的端炏V?<br />5) <strong>CONNECTION_BENDPOINTS_ROLE</strong>: q个Role允许用户能够在一个Connection中间拖动和创建bendpoints?<br />6) <strong>SELECTION_FEEDBACK_ROLE</strong>: q个角色只是用来昄feedback。当鼠标q入或者在一个EditPart上暂停时QSelection Tool会发送两个类型的requestlEditPart。安装了q个角色的EditPart能够在此时接受这些请求来改变view的样子,或者弹出tipQlabel{?<br />7) <strong>TREE_CONTAINER_ROLE</strong>: SWT Tree的Layout Role?本地SWT Tree的Layout Role的等L。这个EditPolicy应该在树上显C反馈ƈ计算索引Q就像在file explorer里拖拽一栗?br />over?br /><br /><img src ="http://www.tkk7.com/pandawang/aggbug/40091.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/pandawang/" target="_blank">Long Long Ago</a> 2006-04-09 14:38 <a href="http://www.tkk7.com/pandawang/archive/2006/04/09/40091.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GEF学习记?/title><link>http://www.tkk7.com/pandawang/archive/2006/04/09/40078.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Sun, 09 Apr 2006 04:33:00 GMT</pubDate><guid>http://www.tkk7.com/pandawang/archive/2006/04/09/40078.html</guid><wfw:comment>http://www.tkk7.com/pandawang/comments/40078.html</wfw:comment><comments>http://www.tkk7.com/pandawang/archive/2006/04/09/40078.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/pandawang/comments/commentRss/40078.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/pandawang/services/trackbacks/40078.html</trackback:ping><description><![CDATA[        GEF中的起到关键作用的是EditPartQ而EditPart中v到关键作用的是EditPolicyQ现在来描述一下GEF是如何创Z个图形ƈ昄昄出来的?br />        首先通过单击调色板,会调用一个实现org.eclipse.gef.requests.CreationFactory接口的工厂类Q这个是我们在注册相应的ToolEntry时声明的Q通过传入的参数这个工厂类q道应该创Z个什么类型的model元素。(注意Q这时候因为我们只是纯创徏了一个模型元素,对于它的父元素,位置信息{等都还不清楚,所以一般我们在讄模型元素的构造函数时需要有个无参数的构造方法(或者有默认参数的构造函敎ͼ。)<br />        当单ȝ布上的某个位|后Q相应的信息比如 模型的父元素Q位|信息等{都已经可以定Q将q些信息以及新创建的模型元素本n包装成request传给相应的EditPartQ就是鼠标单d所在的囑Ş元素对应的EditPartQ?br />        q个EditPart会将q个request传给相应的EditPolicyQ至于怎么传递,q不清楚Q估计是q样的,EditPart会传l注册在其上的所有EditPolicyQ而每个EditPolicy都有个getCommandҎQ通过request的type交给相应的getXXXCommandҎ。查看了一下源代码Q发现在AbastractEditPart中有个getCommandҎ正是每个EditPolicy中的getCommandҎ都调用了一遍)?br />       然后EditPolicy处理相应的requestQ具体的是调用getXXXCommadҎ得到处理相应request的CommandQCommand是可以改变模型。上面提到的q种EditPolicy属于NonGraphicalcdQGEF中还包括了一U称为Graphicalcd的EditPolicyQ这UEditPolicy不对模型q行处理Q只是用来修改图形显C(gq种说法不正,它可以更改视囑օ素的位置Q在业务模型和视图模型统一的情况下Q这U图形EditPolicy也会更改模型Q;而NonGraphical的EditPolicy则是不清楚图形元素的Q但它可以对模型q行更改Q因此这UEditPolicy在不同view之间是可以通用的?br />       当模型发生改变后Q注册再其上的EditPart会得到相应的通知Q此Ӟ通过通知中的property信息QEditPart会refreshVisual或者refreshChildrenQ从而视图发生改变?img src ="http://www.tkk7.com/pandawang/aggbug/40078.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/pandawang/" target="_blank">Long Long Ago</a> 2006-04-09 12:33 <a href="http://www.tkk7.com/pandawang/archive/2006/04/09/40078.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>gef学习记一http://www.tkk7.com/pandawang/archive/2006/02/23/32212.htmlLong Long AgoLong Long AgoThu, 23 Feb 2006 14:40:00 GMThttp://www.tkk7.com/pandawang/archive/2006/02/23/32212.htmlhttp://www.tkk7.com/pandawang/comments/32212.htmlhttp://www.tkk7.com/pandawang/archive/2006/02/23/32212.html#Feedback0http://www.tkk7.com/pandawang/comments/commentRss/32212.htmlhttp://www.tkk7.com/pandawang/services/trackbacks/32212.htmlDraw2D is a lightweight system.轻量U系l,指这个绘囄l全部徏立在一个重量的控件上。对于Draw2D他是建立在SWT的Canvas上的?BR>Draw2D的几个部?BR>1.figures
主要功能Q?BR>   1。给一个figure注册和去注册监听器。这个figure会通知在这个figure中的鼠标旉l监听器?BR>   2。结构化的事件。比如figure层次的结构化变化Qfigure的移动和大小调整?BR>   3。当光标从figure上移q时Q光标的改变和显C?BR>   4。在figure的层ơ中操作figure的位|,包括dU除讉K子节点,或者访问他们的父节炏V?BR>   5。存取:figure的layout managerQfigure的size和locationQ还有tooltips?BR>   6。设|获得焦炏V?BR>   7。设|figure的透明度和可视性?BR>   8。进行坐标变换,figure的交叠和撞?BR>   9。绘制?BR>   10。确认?BR>figure有很多subclassQ提供了很多附加的功能。比?BR>  1。shapeQ它包含了非矩Ş的figureQ可以知道如何填充,q提供了对边界的宽和cd的配|,q提供了异或的绘制方法。比如有椭圆Q几何线Q多边ŞQ矩形,圆角矩Ş和三角Ş?BR>  2。widgetQdraw2d包含的figure允许你创量QlightweightQ的部gQwidgetQ,从而在你的draw2d应用E序中需要输入控制时提供支持。这包含大量的按钮,选择框和文本囑ŞQ标{?BR>  3。layer and paneQ这些用来作ؓ子类的容器,他们提供了羃放,滚动和讲figure攄在不同layer上的能力?BR>囑Ş上下?the graphics context)
  当一个figuer需要被l制的时候轻量系l会调用fiuger的一个paintҎ。每一个figure都会得到一个graphical contextQ他是Graphics的一个实例。作为参ClpaintҎ。这个绘图上下文支持囑Ş操作包括l制Q填充图形绘制它的文字。它也提供了囑Ş的状态,q些可以影响囑Ş操作。这些状态包括当前字体,背景前景颜色{等?BR>2.LightweightSystem
LightweightSystem时draw2d的核心。它提供了SWT Canvas控g和在其上建立的draw2dpȝ之间的映。包含三个方面:
  1。the root figure.q个是LightweightSystem$RootFigurecȝ一个实例。这个是用户的root figure的父cR它l承了一些基于SWT Canvas的图形环境,比如字体Q前景背景颜艌Ӏ?BR>  2。the event dispatcher:SWTEventDispatchercdSWT事g传给Draw2D的root figure中相应的部g?BR>  3。the update manager.它负责绘制ƈ更新Draw2dfigure。当一个绘制请求从下层的SWTcanvas传来ӞLightWeightSystem会调用updatemanager中的performUpdateҎ。update manager会l护一个非法的或者需要重ȝfigure的worklist。upate manager会设法尽量连l的它的work listQ这样可以尽量的提高效率。默认的update managerQDaferredUpdateManager允许通过再Display上的用户U程来工作队列异步的更新?BR>对于一个figure的生存周期中Q绘?painting)和确?validating)是主要的处理q程。draw2d会要求一个figureQ调用绘制方法来递归的绘制自己。paint()Ҏ会调用多个绘制方法:
  1。paintFigure()Qfigure递归的绘制自?BR>  2。paintclientarea(): figure递归的绘制子?BR>  3。paintborder():figurel制边界?BR> 当一个figure的size或者location需要重新计时Q将会调用确认?BR>  1。validate()Q要求figure的layout manager去重新布局它的子图
  2。revalidate():调用invalidateQ添加一个图形和它的先L新update manager的invalid list?BR>

Long Long Ago 2006-02-23 22:40 发表评论
]]>
EMF学习记?/title><link>http://www.tkk7.com/pandawang/archive/2006/02/19/31541.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Sun, 19 Feb 2006 12:46:00 GMT</pubDate><guid>http://www.tkk7.com/pandawang/archive/2006/02/19/31541.html</guid><wfw:comment>http://www.tkk7.com/pandawang/comments/31541.html</wfw:comment><comments>http://www.tkk7.com/pandawang/archive/2006/02/19/31541.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/pandawang/comments/commentRss/31541.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/pandawang/services/trackbacks/31541.html</trackback:ping><description><![CDATA[<P><BR>现在来讨Z下emf所生成的几个plugin。一般通过ecore模型可以生成三个插g分别是emf模型Qemf.edit和emf.editor?BR>让我们现在看模型插g<BR>    对于所有的EPackageQ都会生成两个或三个java packageQ本别是base package(*)Qimplemention package(*.impl),tool package(*.util)。其中,W三个包是可选的Q这取决于生成属性的讄Q默认是生成。包?*)也是在生成属性中讄的?BR>    对于所有EClassQ在base package中生成相应的interfaceQ而其java实现则在impl包中Q如果一个EClassl承于另一个EClassQ那么生成的interface和implemention都承于相应的超cȝinterface和implemention。如果这个类有多个超c,那么在eSuperTypes中的W一个class作Z类(primary supertype)。对于这个子cȝ实现它将l承主超cȝ实现Qƈ且实现其他超cL口中的方法?BR>    对于FeatureQgetter和setterҎ在类和接口中被定义。如果一个一个featureQ成员变量)不是volatileQ那么它的g被存储在一个量|fieldQ中。如果一个feature是只ȝQ那么只生成它对应的getterҎ。对于多值属性一般用EList表示Q而单值就用那个属性的cd表示。EList的类型取决于模型的约束,例如Q一个non-containment reference会使用EObjectWithInverseResolvingEList,对于一个containment reference会使用EObjectContainmentWithInverseEList表示?BR>    对于OperationQ在包含c?containing class)的接口中生成一个公共方法标{,在对应的实现中生成实现骨架?BR>    对于DataTypeQ其中EEnum产生于一个承了org.eclipse.common.util.AbstractEnumerator的实现。对于其他的EDataTypeQ是没有接口和实现生成的Q它们的实例化类是直接使用了EAttribute的类型?BR>再来看看edit插gQ?BR>    对于edit插gprovider package中的所有类都有相应的ItemProviderscȝ成。更q一步,对于整个插g有一个EMFPluginClass生成。ItemProvidercȝ承于org.eclipse.emf.edit.provider.ItemProviderAdaptorQ用于适配模型中相应的EObjectQ所有emfcȝ基类Q。当模型对象׃fireNotifyChanged()改变QItemProvider会传送相应的通知Qƈqo其他的。当你生成插件时Q你可以控制哪些通知被过滤?BR>    ItemProvider也管理属性描qͼproperty descriptorsQ对于所有的featur of the classQ通过getImage和getTextҎ来管理类的icon和descrition?BR>    对于所有的ItemProvider都有一个ItemProviderAdaptorFactory?BR>最后时editor插gQ?BR>    对于所有的模型都会再presentation package中生成三个类?BR>     一个多늼辑器Q它l模型创建几个不同的jface viewerQ包含一个TreeViewerQ用edit插g中的ItemProvider作ؓq个treeviewer的content和label的provider。这个editorq创建outline和property来显C在viewer中选中对象的属性?BR>     一个ActionBarContributorQ它被用于对~辑器视图中选中的item所创徏的context menud选项?BR>     最后是一个向|允许你创Z个包含模型对象的一个实例的资源(resource)?/P> <P>    </P> <P> </P><img src ="http://www.tkk7.com/pandawang/aggbug/31541.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/pandawang/" target="_blank">Long Long Ago</a> 2006-02-19 20:46 <a href="http://www.tkk7.com/pandawang/archive/2006/02/19/31541.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EMF学习W记一http://www.tkk7.com/pandawang/archive/2006/02/19/31472.htmlLong Long AgoLong Long AgoSun, 19 Feb 2006 07:32:00 GMThttp://www.tkk7.com/pandawang/archive/2006/02/19/31472.htmlhttp://www.tkk7.com/pandawang/comments/31472.htmlhttp://www.tkk7.com/pandawang/archive/2006/02/19/31472.html#Feedback0http://www.tkk7.com/pandawang/comments/commentRss/31472.htmlhttp://www.tkk7.com/pandawang/services/trackbacks/31472.htmlEMF中的三个部分Q元数据meta-data,代码生成code generation,默认序列化default serialization.
EMF is part of the Model Driver Architecture(MDA).MDA是将整个应用软g生存周期的开发管理都集中于模型上。这U模型是用元模型(meta-model)定义的。然后,使用映射Q模型被用于生成software artefacts, q就实现了整个系l?BR>EMF所能做的:emf能够用于描述和构建模型。所实现的模型可以被用于Mjava应用E序的开发?BR>对于ecore模型我们有几炚w要注意:
1。在ecore文g的xmi描述中没有各个元素之间的联系Q我们用EReference来表C各个元素之间的联系?BR>   对于两个方向上的联系Q通过两个成对的EReference来表C,每个联系的类Q都有一个eOpposite来保存它自己在所联系cM的名字(引用Q?BR>   对于单方向上的联p,使用一个单独的EReferenceQƈ且这个reference没有eOppositeQ因为对方ƈ没有对自q引用Q?BR>   q接的多重性通过upperBound和lowerBound来表C。多个用-1?BR>2。用EPackage可以像java中的package一L?BR>3。两U模型,一U是业务模型Q一U是视图模型。一般将两种模型攑֜不同的package中。两U方法将两种模型联系hQ?BR>   一是构Z个新packageQ构Z个多重承的新package来将两个package联系h?BR>   二是两U模型分开存储Q添加从视图模型C务模型的引用。这U方法两个模型是松耦合的。这U单方向的引用也不会破坏Q污染)业务模型。注意,׃q种引用是两个package之间的,所以在Uȝ的eTypecd中需要指明包名?nbsp; 

除此之外Qecoreq提供了一U递归的定义方法。就是用eSubPackage来分别包含业务模型和视图模型Qƈ且在q两个subPackage间徏立referenceQ对于package来说是自己引用自己)?BR>4。我们可以有多种Ҏ来生成ecore模型。通过注释的java接口(annotated java interface),通过rantional rose创徏模型Q通过XML Schema{等?/P>

Long Long Ago 2006-02-19 15:32 发表评论
]]>
GMF学习记?Step by stephttp://www.tkk7.com/pandawang/archive/2006/02/15/30760.htmlLong Long AgoLong Long AgoWed, 15 Feb 2006 02:37:00 GMThttp://www.tkk7.com/pandawang/archive/2006/02/15/30760.htmlhttp://www.tkk7.com/pandawang/comments/30760.htmlhttp://www.tkk7.com/pandawang/archive/2006/02/15/30760.html#Feedback0http://www.tkk7.com/pandawang/comments/commentRss/30760.htmlhttp://www.tkk7.com/pandawang/services/trackbacks/30760.html以下是简单的步骤Q?BR>单的使用ҎQ首先应该定义ecore模型文g有很多种ҎQ比如用EclipseUML插gQ或者用gmf的exampleU的Ecore DiagramQ这些图形化的类囄辑工具都可以方便的生成我们所需要的Ecore文g。这里我们用的是EclipseUML的免费版本。是针对eclipse3.1的,不过好像3.2m1m2都可以用?BR>生成ecore文g?File/new/other/Eclipse Modeling Framwork/EMF Model 生成相应的genmodel文gQ通过它来生成模型?edit插gQ这些都是GMF所需要的。然后再File/New/other/Example EMF Model Creation Wizards/GMFGraph Model 注意名字应该都是一LQ扩展名不同Q最后的Model Object选择Canvas。在生成的gmfgraph文g中给canvas命名Qcanvasq当于我们的画布。在canvas下创Z个figure galleryQ图库)Q在q里我们保存所需要的囑Ş?BR>然后创徏gmftool文gFile/New/other/Example EMF Model Creation Wizards/GMFTool ModelQ可以用File/New/other/GMF/GMFTool Simple Model来简单的构造?BR>再创建gmfmap文gQ徏立模型和囑Ş之间的映关pRFile/New/other/Example EMF Model Creation Wizards/GMFMap ModelQ名字应该和前面的一P最后的Model Object选择Mapping。在生成的gmfmap文g中右键选择Load ResourceQ选择ecoreQgmfgraphQgmftool文g。ƈ且生成相应的映射信息Q比如node mapping和canvas mapping?BR>最后生成emf模型代码和edit代码Q用genmodel文g?BR>使用gmfmap文g右键生成gmfgen文gQ注意我们要有genmode文g才能生成gmfgen文g?BR>最后用gmfgen生成editor插g。这时候共有三个插?模型 edit和editor?BR>使用时File/New/other/Example/中有个相应的diagramQ一般再最上面Q给一个名字,无扩展名Q就打开相应的编辑器了?img src ="http://www.tkk7.com/pandawang/aggbug/30760.html" width = "1" height = "1" />

Long Long Ago 2006-02-15 10:37 发表评论
]]>
GMF学习记一http://www.tkk7.com/pandawang/archive/2006/02/14/30564.htmlLong Long AgoLong Long AgoTue, 14 Feb 2006 03:38:00 GMThttp://www.tkk7.com/pandawang/archive/2006/02/14/30564.htmlhttp://www.tkk7.com/pandawang/comments/30564.htmlhttp://www.tkk7.com/pandawang/archive/2006/02/14/30564.html#Feedback0http://www.tkk7.com/pandawang/comments/commentRss/30564.htmlhttp://www.tkk7.com/pandawang/services/trackbacks/30564.htmlGMF有可能成Z个标准的Eclipse囑Ş模型~辑器,它分Z个部分:q行Ӟthe runtimeQ和工具QtoolingQ,工具是由一些创建和~辑W号语义模型的编辑器l成的,工具q包含了囑Ş~辑器,q且有图形编辑器的生成器?/P>

使用GMF开发一个类囑Ş模型~辑器的步骤如下Q?BR>
1。创建域模型Q这个模型描qC通过~辑器编辑的非图形信息?BR>2。创建图定义模型Q这个模型描qC昄在图形编辑器中的囑Ş元素?BR>3。创建图映射模型Q这个模型定义了域模型元素和囑Ş元素之间的对应关pR?BR>4。生成图形编辑器?BR>5。通过改进生成的代码来提高囑Ş~辑器?BR>介绍一点GMF的图形编辑器的特性:
1。折?BR>2。label的直接编?BR>3。提C?BR>4。弹出bar
5。连接柄
6。通用l图工具
7。通用菜单命o
8。通用工具?BR>9。自动羃攑֒布局
10。通用属性编?BR>11。打印和打印预览
12。SVG和剪贴板支持

http://www.eclipse.org/articles/Article-Introducing-GMF/article.html



Long Long Ago 2006-02-14 11:38 发表评论
]]>
一个用RCP实现的简单的GEFE序http://www.tkk7.com/pandawang/archive/2006/01/12/27754.htmlLong Long AgoLong Long AgoThu, 12 Jan 2006 06:35:00 GMThttp://www.tkk7.com/pandawang/archive/2006/01/12/27754.htmlhttp://www.tkk7.com/pandawang/comments/27754.htmlhttp://www.tkk7.com/pandawang/archive/2006/01/12/27754.html#Feedback0http://www.tkk7.com/pandawang/comments/commentRss/27754.htmlhttp://www.tkk7.com/pandawang/services/trackbacks/27754.html八进?/A>的例子。在q里做一下ȝ。先来介l一下gefQ网上关于GEF的介l越来越多,从另一斚w也说明这个技术确实在热v来,不过GEFZ实现可扩放性和可重用性,做的很是复杂Q闲话一下,最q看了一本书《Better.Faster.Lighter.Java》,没看多少QJustin Gehtland, Bruce A. Tate写的Q一开始就说了Qؓ了满来越多的需要,各种frameworkQlibraryQlanguage都是来复杂了Q学习曲U也变得陡峭了,q个g是无法避免的Qjava语言也是Q不信去看看jdkQ?.1时才3.7MBQ?.4时已l?8MB了。我也一直坚信,Simply the bestQ呵呵)?
       GEF的一些资源:
          1?A >www.eclipse.org q个是源头啊Qfaq也可以看?nbsp;
          2。ibm的dW 除了相关文章Q这里还有本关于gef和emf的红宝书Q可?A href="http://http://publib-b.boulder.ibm.com/Redbooks.nsf/RedbookAbstracts/sg246302.html">免费下蝲?
          3。eclipseworld.org q个是一个关于eclipse中文C֌
          4。八q制的blog http://bjzhanghao.cnblogs.com/ ?
          5。这里还有些中文教程 http://www.benisoft.com/cn/index.htm
          6。还有一些blog http://www.tkk7.com/hopeshared/  http://www.tkk7.com/eclipshine/ http://www.tkk7.com/reloadcn/ http://www.tkk7.com/USTCEric
      好了Q现在来介绍一下GEF的实现机Ӟ主要是我的一些理解可能还有一不对的地方,Ƣ迎大家帮我Ҏ?BR>      GEF是具有标准MVCQModel-View-ControlQ结构的囑Ş~辑框架Q其中Model由我们自己根据业务来设计Q它要能够提供某U模型改变通知的机Ӟ用来把Model的变化告诉Control层;Control层由一些EditPart实现QEditPart是整个GEF的核心部Ӟ?View层,大多数情况下Q用Draw2D实现了,其作用是把Model以图形化的方式表现给使用者,当然你也可以使用其他囑Ş包,不过gef?Draw2D的结合还是非常紧密的Q一般ؓ了用方便,View都是使用Draw2D实现的?BR>        关于Draw2DQ八q制有一相应的文章Q还有eclipse上的一?A >文章Q可以参考,q里有几炚w要强调一下:
         1。Draw2D提供了很多缺省图形,最常见的有三类Q?、ŞӞShapeQ,如矩形、三角Ş、椭圆Ş{等Q?、控ӞWidgetQ,如标{、按钮、滚动条{等Q?、层QLayerQ,它们用来为放|于其中的图形提供羃放、滚动等功能?BR>        2。每个图形都可以拥有一个边框(BorderQ,Draw2D所提供的边框类型有GroupBoxBorder、TitleBarBorder、ImageBorder?ButtonBorderQ以及可以组合两U边框的CompoundBorder{等Q在Draw2D里还专门有一个Insetscȝ来表C框在囑Ş中所占的位置Q它包含上下左右四个整型数倹{?BR>        3。一个图形可以包含很多个子图形,q些被包含的囑Ş在显C的时候必M某种方式被排列v来,负责q个d的就是父囑Ş的LayoutManagerQ相应的U束QConstraintQ对象就在这里,比如在子囑ŞhQrefreshVisualsQ时可以通过其布局U束传递给其父元素来定位?BR>        4。利用Draw2D中的Router、Anchor和LocatorQ可以实现多U连接样式。Router负责q接U的外观和操作方式;Anchor控制q接U端点在囑Ş上的位置Q即"锚点"的位|;Locator的作用是定位囑Ş?BR>        前面说过了GEF是通过MVC架构实现的,下面分别介绍q三个方面:
        一、模型(ModelQ:q个是相Ҏ较容易理解,模型保存着业务逻辑Q他是GEFq中唯一可以持久化的Qƈ且需要提供相应的监听机制Q来通知 EditPartL新ViewQ监听机制又可以分ؓ分布式和集中式两U,我们可以针对域监听器q行转有通知Q也可以全局q播Q在q里我们认ؓ CommandQEditPart用来更新模型的对象)也是模型的一个部分,因ؓ它了解模型。此外,在有时候可能需要多U模型。我们对于业务模型,提供一个“视䏀模型,q样便于实现和满相应的要求Q不内部模型是怎么LQ都要实现通知机制?BR>      二、视图。GEF提供了在EclipseWorkbench中用ViewerQ称为EditPartViewer。它的作用和jface中的 Viewer很相Q不q这时候它的ContentProvider和LabelProvider是EditPartQ通过setContents讄Q注意在八进制代码中setContents参数为模型对象,通过分析发现Q在AbstractEditPartViewer中此Ҏ被重载,可以除了接受 org.eclipse.gef.editpart对象外可以接受Object对象Q不q此时回调用EditPartFactoryQ通过l定的模型对象来创徏相应的EditPartQ个样做q不与“View与Model无直接联pZ的要求相矛盾)。这个接口承了 org.eclipse.jface.viewers.ISelectionProvider接口Q这个也和jface中的viewer一PQ因此 viewer提供了监听器Q这样可以将对view的操作传递到editpart。EditPartViewer会维护各个EditPart的选中状态,如果没有被选中的EditPartQ则~省选中的是作ؓcontents的EditPart?BR>         EditPartViewer可以适配CQ何一个SWT控gQ因为它要求有createControlҎQ接受一个父SWT控g作ؓ适配对象Q从而将 GEF生成的Figure对象昄在这个SWT控g上,因此GEF可以使用M囑Ş包,不过GEF提供了对Draw2D的默认实玎ͼ比如 AbstractGraphicalEditPartcM的回调方法createFigurep求返回一个IFigure对象。将一个GEF囑Ş昄出来可以使用org.eclipse.ui.part.EditorPart也可以是org.eclipse.ui.part.ViewPartQ如果?EditorPartQ则需要实现承自WorkbenchPart的createPartControl,如果是ViewPart则需要自己实C GEF的交互,不过Eclipse Workbench对viewpart和editorpart的支持是一LQ都是在plugin文g扩展相应的扩展点。一般来_使用GEF?Editorpart的模式实现是非常方便的?BR>      GEF目前提供两种视图分别是GraphicalViewer和TreeViewerQ都间接l承了EditPartViewer接口Q前者利?Draw2D囑ŞQIFigureQ作现方式,多用于编辑区域,后者则多用于实现大U展C,q且他们有两个具体的实现Q分别是 ScrollingGraphicalViewer和TreeViewer。其中ScrollingGraphicalViewerQ通过分析GEF源代码可知,是GraphicalEditor中Viewer的默认实玎ͼ我们可以通过GraphicalEditorcL供的 setGraphicalViewer(GraphicalViewer)Ҏ重新讄其他viewer。我们在使用的时候通过 configureGraphicalViewer和initializeGraphicalViewerҎ来配|GraphicalViewer。所不同的是Q在configureGraphicalViewer之后initializeGraphicalViewer之前插入了一?hookGraphicalViewerҎQ其作用是同步选择和把 EditPartViewer作ؓSelectionProvider注册到所在的siteQ其成为SelectionProvider?BR>       此外QGEF中还提供一U成色板QPaletteViewerQ的视图Q它也是间接实现了EditPartViewer接口。因此,我也像配|GraphicalViewer一h配置PaletteViewerQ类似的使用 configurePaletteViewer和initializePaletteViewerҎQ其间类似的插入了一?hookPaletteViewerҎQ用于设|相应EditDomain的PaletteViewer?BR>       最后,ȝ一下如何配|GraphicalViewQ主要是四个斚wQ?BR>      1。设|一个RootEditPartQRootEditPart的是使整个GEF框架q行h的关键之一。RootEditPartq不对应于Q何的模型对象Q它从setContents()Ҏ中接收到的模型对象进行{换,q添加到整个的EditPart体系中去?BR>       2。设|其EditPartFactoryQ负责从模型到EditPart的{换。一般来说一个模型对象对应于一个EditPart?BR>       3。设|EditDomainQ用来接收事件ƈ选择恰当的事件处理函数进行处理,q个主要是ؓ了相应view所接收到的用户的操作?BR>       4。调用setContents()ҎQؓ其设|要昄的内宏V?BR>       三、控制器QEditPartQ。这是GEF最核心的地方了Q它model和view联系h。程序员可以l承三种EditPartQ分别是 org.eclipse.gef.editparts.AbstractGraphicalEditPartQorg.eclipse.gef.editparts.AbstractConnectionEditPartQAbstractGraphicalEditPart的子c)和org.eclipse.gef.editparts.AbstractTreeEditPart?/B>EditPart 的生命周期当setContentsӞ模型对象输入,此对象ؓ层对象Q通过它可以遍历所有的模型对象。:EditPartViewer配备?EditPartFactoryQEditPartViewer通过EditPartFactory构造相应的Contents EditPart。然后EditPartViewer中的每个EditPart通过EditPartFactory构造相应的子EditPart。当用户d新的模型的时候,包含q些模型对象的所对应的EditPart构造相应的EditPart作出相应。视囄构造和EditPart的构造是同时q行的,每当EditPart构造ƈd到它的父EditPart后相应的view也做同样的事情,比如GraphicalEditor中就?GraphicalViewer成员变量Q在此edipart创徏时回调用createPartControlQ在q个Ҏ中将会创建相应的viewQƈ其加入到父view中?BR>       一旦用户丢弃了某些模型对象Q相应的EditPart׃被丢弃。比如用h行了删除操作Q则相应的模型对象和相应的EditPart都被删除了,但用h销了删除操作而重新创建的EditPart与原来的EditPart是不同的Q所以EditPart是不能保存长期信息的Q应该交l模型去保存Qƈ?EditPart也是不能被Command所引用?BR>    在具体用时Q应该先定一个Contents EditPart,它的父元素ؓEditPartViewer的RootEditPart。RootEditPart是EditPartView?rootQ它EditPartView和它的contentsQ一般认为是层模型对象所对应的EditPartQ联pv来,RootEditPart 为用LEditPart提供一致性的上下文(contextQ。ƈ且,当没有被选中的模型EditPartӞ层对象的EditPart是默认被选中的,而RootEditPart是不能被选中的或者定位的Q甚至不能与用户怺互,他也没有对应的模型对象。GEF提供了几个默认的 RootEditPart的实玎ͼFreeformGraphicalRootEditPart,RootTreeEditPart, ScalableRootEditPartQScalableFreeformRootEditPartQ此cȝ承于 FreeformGraphicalRootEditPartQ增加了~放Zoom支持Q提供了ZoomManagerQ增加了一个LayerPaneQ?ScalableFreeformLayeredPane。)Q(原来q有个GraphicalRootEditPartQ已ldeprecatedQ用 ScalableRootEditPart代替Q。这里要注意的是Q?BR>    1)对于FreeformRootEditPartQ以及它的子c?ScalableFreeformRootEditPartQ,它的Contents EditPart应该有一?FONT size=-1>org.eclipse.draw2d.FreeformFigure对象Q比如FreeformLayer或FreeformLayeredPaneQ作为它的Figure。例如在我们的代码里Q对应的是?DiagramPart中的createFigureҎQ它q回了一个FreeformLayer对象?BR>    2) FreeformGraphicalRootEditPart的Primery Layer没有使用draw2d的LayoutManagerQƈ且,除非contents的figure是个freeform figureQ否则不能正的调整大小?BR>    3)FreefromGraphicalRootEditPart使用FreeformViewportcM为它的primary figureQ这个类必须和ScrollingGraphicalViewer使用?BR>    4)ScalableRootEditPart使用 Viewport作ؓprimery figureQ这个类必须和ScrollingGraphicalViewer使用?BR>    5)RootTreeEditPart是TreeViewer的RootEditPart?BR>    Contents EditPart的图形一般是一个空面板Q该面板包含diagram的子图?BR>    我们q要定义其他“视䏀模型的EditPartQ比如节点(nodeQ,q接QconnectionQ。对于节点,是GraphicalQ可以?AbstractGraphicalEditPart。ƈ且可以实现NodeEditPart接口Q则可以支持源和目标?ConnectionEditPartQ用AnchorQ具体在下面有讲q。在q里Q我们的代码的NodePartcMQ重载了 refreshVisualҎQ其中设|figure的布局U束是通过它的父元素来定位的,我不知道q是不是标准的方法,XYLayout使用的是 rectangleU束Q如果长宽设为-1Q表CZؓ该图形提供理惛_。不要用setBoundsQXYLayout布局理器可以保证对滚动条进行更斎ͼq能相对约束{化ؓl对U束Q如果长宽设|ؓQ?Q则能够图形设|ؓ理想的大。此外,Z改进性能Q我们可以将refreshVisual中有若干模型的分别刷斎ͼ或者设|是否需要刷新的开兟?BR>    对于q接Q可以承AbstractConnectionEditPartQ这个抽象类已经实现?ConnectionEditPart。和Node实现一P通过refreshVisualҎ属性从模型映射到图形。连接也可以有约束,不过与前面的U束不尽相同。在q里Q连接\由器Qconnection routerQ用约束来是连接{向(bendQ。需要注意的是,一个Connection EditPart的图形必L一个draw2d的ConnectionQ这样就引入了连接锚QConnection AnchorQ。连接必ȝq接锚(ConnectionAnchorQ“锚定”在两端。因此,需要在q接EditPart或者节点EditPart中实C用什么样的锚。缺省情况下QGEF使用节点EditPart通过实现NodeEditPart接口来提供锚。这是因为,锚的选择取决与各个节点上正在使用的图形,而连接EditPart不应了解节点上的囑ŞQƈ且,当用户创接的时候,q接EditPartq没有创建,q时候就p点自己显C反馈。这里需要注意的是:何时使用以及何时不用ConnectionEditPartQ当用户可以选择某些东西q可与之交互Ӟ需?ConnectionEditPart。它可能与某行中的某个对象相对应Qƈ且回自己删除Q如果这是需要一个绘制直U的节点或者容器,那么只需要用囑Ş?paintҎl制直线Q或者组合一个图形,q个囑Ş包含Polyline囑Ş。连接必要拥有源和目标。如果要创徏一个连接,q且在没有源和目标存在的情况下,可以l承AbstractGraphicalEditPartQƈ使用q接囑ŞQ比如PolylineConnection?BR>    正如前面说的Q模型需要实现某U通知机制Q各个EditPart要将自己做ؓ监听者,注册在模型上Q以便在模型发生改变的时候收到相应的通知?  当EditPart收到相应的通知Ӟ调用相应的处理方法,来进行一ơ强制的hQ对于模型对象的增减可以调用refreshChildrenҎQ对于简单属性的更改可以调用refreshVisualsҎQ这Ӟ像前面提到的Q可以只h改变的部分,以提高性能。一般,我们在ActivateҎ中注册监听器Q在DeactivateҎ中注销监听器?BR>    以上完成的是从模型到视图的映,你还需要实现的是编辑策略Edit PoliciesQ因为EditPartq不直接Ҏ型进行编辑,每一个EditPolicy都针对一个特定的~辑d或者一l相关的工作。这L实现便于在不同的EditPart间重用(reuseQ编辑行为,q且q样的实玎ͼ可以动态的改变行ؓQ比如改变layout或者routing时。在 createEditPoliciesҎ中,我们要insall我们的的PoliciesQ这时候就需要rolesQroles的作用就是作为关键字来标CZ同的policies。policy中提供CommandQ每个应用程序都有个Command栈,Command的运行要通过Command栈,而不是直接调用executeҎ?BR>    说到q里Q要注意EditPartView是视囄Q一般放在一个UI插g上比如EditorPartQviewPartQ甚至swt控g。EditPart是控制器Q联p视囑֒模型?BR>    在本文的最后介l一下GEF的运行机ӞEditPartView接受用户的操作,如节点的UdQ增删,每个节点对应一个EditPart对象Q每?EditPart都有一l由Role区分的EditPoliciesQ每个EditPolicy会对应一些Command对象QCommand最l会Ҏ型进行操作。用L操作会{化ؓRequest分配l特定的EditPolicyQ由EditPolicy创徏相应的CommandҎ型进行操作,q些 Command会保留在EditDomain的命令堆栈中Q用于实现undoQredo功能QEditDomain是专门用于维?EditPartViewQCommand信息的对象,一般每个EditPart有一个EditDomain?BR>    以上是Ҏ作的GEF部分的大概描qͼ可能有些地方写的比较|嗦Q有的地方写的也可能不对Q希望大家指出,谢谢。下面还要对RCP部分q行一些描q?BR>

Long Long Ago 2006-01-12 14:35 发表评论
]]>
վ֩ģ壺 ҹþӰԺ| ޾AA߹ۿSEE| ޵һ| Ƶۿ| ҹƷһţӰԺ | ޳aƬ߿| ѹۿվ߲| һ| ɫse01Ƶ| պ޲ƵĻ߹ۿ| 91ѹۿ| ޵Ӱһ| ԻԻ³ҹҹѲƵ| ձ| þþþѿ| ŮһëƬѹۿ| ޾Ʒ͵Ƶѹۿ | ޵һҳۺͼƬ| ѻɫƵ | Ůžžѹۿվ| AVһ| ˾þۺ| 99ƷƵѹۿ| һĻߵӰ | һؼŮ18ëƬƵ| ޾ƷԴ26u| ߿Ƭ˳Ӿ| Ļ | ߹ۿƵվ| Ʒ| ëƬѹۿ| Ƶ߹ۿӰԺ| 51ҹƷƵ| ձ㽶ƵۿƵ| ĻAV߾Ʒѹۿ| | ŷղ| h⶯߹ۿ| ˶wwwҹվ| Ļ| 99ƷƵ|