八进制

少年壮志无烟抽

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  231 随笔 :: 0 文章 :: 2955 评论 :: 11 Trackbacks

构造一个GEF应用程序通常分为这么几个步骤:设计模型、设计EditPart和Figure、设计EditPolicy和Command,其中 EditPart是最主要的一部分,因为在实现它的时候不可避免的要使用到EditPolicy,而后者又涉及到Command。

现在我们来看个例子,它的功能非常简单,用户可以在画布上增加节点(Node)和节点间的连接,可以直接编辑节点的名称以及改变节点的位置,用户可以撤消/重做任何操作,有一个树状的大纲视图和一个属性页。点此下载(Update: For Eclipse 3.1的版本),这是一个Eclipse的项目打包文件,在Eclipse里导入后运行Run-time Workbench,新建一个扩展名为"gefpractice"的文件就会打开这个编辑器。

图1 Practice Editor的使用界面

你可以参考着代码来看接下来的内容了,让我们从模型开始说起。模型是根据应用需求来设计的,所以我们的模型包括代表整个图的Diagram、代表节 点的Node和代表连接的Connection这些对象。我们知道,模型是要负责把自己的改变通知给EditPart的,为了把这个功能分离出来,我们使 用名为Element的抽象类专门来实现通知机制,然后让其他模型类继承它。Element类里包括一个PropertyChangeSupport类型 的成员变量,并提供了addPropertyChangeListener()、removePropertyChangeListener()和 fireXXX()方法分别用来注册监听器和通知监听器模型改变事件。在GEF里,模型的监听器就是EditPart,在EditPart的active ()方法里我们会把它作为监听器注册到模型中。所以,总共有四个类组成了我们的模型部分。

在前面的贴子里说过,大部分GEF应用程序都是实现为Editor的,这个例子也不例外,对应的Editor名为PracticeEditor。这 个Editor继承了GraphicalEditorWithPalette类,表示它是一个具有调色板的图形编辑器。最重要的两个方法是 configureGraphicalViewer()和initializeGraphicalViewer(),分别用来定制和初始化 EditPartViewer(关于EditPartViewer的作用请查看前面的帖子),简单查看一下GEF的代码你会发现,在 GraphicalEditor类里会先后调用这两个方法,只是中间插了一个hookGraphicalViewer()方法,其作用是同步选择和把 EditPartViewer作为SelectionProvider注册到所在的site(Site是Workbench的概念,请查Eclipse帮 助)。所以,与选择无关的初始化操作应该在前者中完成,否则放在后者完成。例子中,在这两个方法里我们配置了RootEditPart、用于创建 EditPart的EditPartFactory、Contents即Diagram对象和增加了拖放支持,拖动目标是当前 EditPartViewer,后面会看到拖动源就是调色板。

这个Editor是带有调色板的,所以要告诉GEF我们的调色板里都有哪些工具,这是通过覆盖getPaletteRoot()方法来实现的。在这 个方法里,我们利用自己写的一个工具类PaletteFactory构造一个PaletteRoot对象并返回,我们的调色板里需要有三种工具:选择工 具、节点工具和连接工具。在GEF里,调色板里可以有抽屉(PaletteDrawer)把各种工具归类放置,每个工具都是一个ToolEntry,选择 工具(SelectionToolEntry)和连接工具(ConnectionCreationToolEntry)是预先定义好的几种工具中的两个, 所以可以直接使用。对于节点工具,要使用CombinedTemplateCreationEntry,并把节点类型作为参数之一传给它,创建节点工具的 代码如下所示。

ToolEntry tool = new CombinedTemplateCreationEntry("Node""Create a new Node", Node.class, new SimpleFactory(Node.class), nullnull);

在新的3.0版本GEF里还提供了一种可以自动隐藏调色板的编辑器GraphicalEditorWithFlyoutPalette,对调色板的外观有更多选项可以选择,以后的帖子里可能会提到如何使用。

调色板的初始化操作应该放在initializePaletteViewer()里完成,最主要的任务是为调色板所在的 EditPartViewer添加拖动源事件支持,前面我们已经为画布所在EditPartViewer添加了拖动目标事件,所以现在就可以实现完整的拖 放操作了。这里稍微讲解一下拖放的实现原理,以用来创建节点对象的节点工具为例,它在调色板里是一个 CombinedTemplateCreationEntry,在创建这个PaletteEntry时(见上面的代码)我们指定该对象对应一个 Node.class,所以在用户从调色板里拖动这个工具时,内存里有一个TemplateTransfer单例对象会记录下Node.class(称作 template),当用户在画布上松开鼠标时,拖放结束的事件被触发,将由画布注册的 DiagramTemplateTransferDropTargetListener对象来处理template对象(现在是Node.class), 在例子中我们的处理方法是用一个名为ElementFactory的对象负责根据这个template创建一个对应类型的实例。

以上我们建立了模型和用于实现视图的Editor,因为模型的改变都是由Command对象直接修改的,所以下面我们先来看都有哪些 Command。由需求可知,我们对模型的操作有增加/删除节点、修改节点名称、改变节点位置和增加/删除连接等,所以对应就有 CreateNodeCommand、DeleteNodeCommand、RenameNodeCommand、MoveNodeCommand、 CreateConnectionCommand和DeleteConnectionCommand这些对象,它们都放归类在commands包里。一个 Command对象里最重要的当然是execute()方法了,也就是执行命令的方法。除此以外,因为要实现撤消/重做功能,所以在Command对象里 都有Undo()和Redo()方法,同时在Command对象里要有成员变量负责保留执行该命令时的相关状态,例如RenameNodeCommand 里要有oldName和newName两个变量,这样才能正确的执行Undo()和Redo()方法,要记住,每个被执行过的Command对象实例都是 被保存在EditDomain的CommandStack中的。

例子里的EditPolicy都放在policies包里,与图形有关的(GraphicalEditPart的子类)有 DiagramLayoutEditPolicy、NodeDirectEditPolicy和 NodeGraphicalNodeEditPolicy,另外两个则是与图形无关的编辑策略。可以看到,在后一种类型的两个类 (ConnectionEditPolicy和NodeEditPolicy)中我们只覆盖了createDeleteCommand()方法,该方法用 于创建一个负责"删除"操作的Command对象并返回,要搞清这个方法看似矛盾的名字里create和delete是对不同对象而言的。

有了Command和EditPolicy,现在可以来看看EditPart部分了。每一个模型对象都对应一个EditPart,所以我们的三个模 型对象(Element不算)分别对应DiagramPart、ConnectionPart和NodePart。对于含有子元素的EditPart,必 须覆盖getModelChildren()方法返回子对象列表,例如DiagramPart里这个方法返回的是Diagram对象包含的Node对象列 表。

每个EditPart都有active()和deactive()两个方法,一般我们在前者里注册监听器(因为实现了 PropertyChangeListener接口,所以EditPart本身就是监听器)到模型对象,在后者里将监听器从列表里移除。在触发监听器事件 的propertyChange()方法里,一般是根据"事件名"称决定使用何种方式刷新视图,例如对于NodePart,如果是节点本身的属性发生变 化,则调用refreshVisuals()方法,若是与它相关的连接发生变化,则调用refreshTargetConnections()或 refreshSourceConnections()。这里用到的事件名称都是我们自己来规定的,在例子中比如Node.PROP_NAME表示节点的 名称属性,Node.PROP_LOCATION表示节点的位置属性,等等。

EditPart(确切的说是AbstractGraphicalEditpart)另外一个需要实现的重要方法是createFigure(), 这个方法应该返回模型在视图中的图形表示,是一个IFigure类型对象。一般都把这些图形放在figures包里,例子里只有NodeFigure一个 自定义图形,Diagram对象对应的是GEF自带的名为FreeformLayer的图形,它是一个可以在东南西北四个方向任意扩展的层图形;而 Connection对应的也是GEF自带的图形,名为PolylineConnection,这个图形缺省是一条用来连接另外两个图形的直线,在例子里 我们通过setTargetDecoration()方法让连接的目标端显示一个箭头。

最后,要为EditPart增加适当的EditPolicy,这是通过覆盖EditPart的createEditPolicies()方法来实现 的,每一个被"安装"到EditPart中的EditPolicy都对应一个用来表示角色(Role)的字符串。对于在模型中有子元素的 EditPart,一般都会安装一个EditPolicy.LAYOUT_ROLE角色的EditPolicy(见下面的代码),后者多为 LayoutEditPolicy的子类;对于连接类型的EditPart,一般要安装 EditPolicy.CONNECTION_ENDPOINTS_ROLE角色的EditPolicy,后者则多为 ConnectionEndpointEditPolicy或其子类,等等。

installEditPolicy(EditPolicy.LAYOUT_ROLE, new DiagramLayoutEditPolicy());

用户的操作会被当前工具(缺省为选择工具SelectionTool)转换为请求(Request),请求根据类型被分发到目标EditPart所安装的EditPolicy,后者根据请求对应的角色来判断是否应该创建命令并执行。

在以前的帖子里说过,Role-EditPolicy-Command这样的设计主要是为了尽量重用代码,例如同一个EditPolicy可以被安 装在不同EditPart中,而同一个Command可以被不同的EditPolicy所使用,等等。当然,凡事有利必有弊,我认为这种的设计也有缺点, 首先在代码上看来不够直观,你必须对众多Role、EditPolicy有所了解,增加了学习周期;另外大部分不需要重用的代码也要按照这个相对复杂的方 式来写,带来了额外工作量。

以上就是一个GEF应用程序里最基本的几个组成部分,例子中还有如Direct Edit、属性表和大纲视图等一些功能没有讲解,下面的帖子里将介绍这些常用功能的实现。

posted on 2005-02-19 13:57 八进制 阅读(29696) 评论(258)  编辑 收藏 所属分类: EclipseGEF
评论共2页: 1 2 下一页 

评论

#1楼 [楼主] 2005-07-20 22:37 八进制      
可以试试覆盖ScalableRootEditPart或FreeformGraphicalRootEditPart类(视你在程序用哪个作为RootEditPart而定)的createPrintableLayers()方法,我觉得把两个layer的顺序颠倒一下应该就可以了。
  回复  引用  查看    

#2楼  2005-07-22 14:05 liuyu [未注册用户]
非常感谢,的确换一下顺序就能克服这个问题了,现在还有两个问题想请教:
第一,如果是同一个Layer的part,比如2个Activity,他们的前后顺序好像是按照他们拖放上来的先后顺序所决定的吧,后放上来的肯定会把前面放上来的遮掉,有没有改变这种状态呢?还是说无法改变的?
第二,现在按照你的例子,Activity上的文字都是写在Activity的中央的,如果我想改变这文字的位置,比如放在Activity的下方应该怎么做呢?
  回复  引用    

#3楼 [楼主] 2005-07-23 00:24 八进制      
第一个问题,是不是可以给用户一个“把图形提前”的选项,点它后你让layer先remove掉这个图形,再加进来,它就应该在最前面了。
第二个问题,改Activity图形类即可实现。
  回复  引用  查看    

#4楼  2005-07-23 20:42 liuyu [未注册用户]
第一个问题的确可以用这个方法解决,第二的问题我还是不会改,现在的代码里就是直接this.add(label);,这样的话肯定会加在中央,但是设置label的location没有用,始终在Activity的中央,到底应该怎么改呢?
  回复  引用    

#5楼 [楼主] 2005-07-23 22:09 八进制      
label的位置由它所在图形的layout manager决定
  回复  引用  查看    

#6楼  2005-07-24 15:56 liuyu [未注册用户]
我在ActivityFigure里用ToolbarLayout对其进行设置后,刚把Activity放上去的时候成功了,label的确在图形下面,但是问题是一拖动图形label又会跑到图形中间去了,不知道为什么。
  回复  引用    

#7楼  2005-07-30 13:43 xiaodao [未注册用户]
感觉楼主谆谆教导~!~!~!~!~!~!~!~!~!~!~
  回复  引用    

#8楼  2005-08-06 17:05 lucia [未注册用户]
非常感谢你的文章,是我读的有关gef里写得最好的了。我因为刚刚接触,所以对我现在要编写的东西还有些迷糊,所以请教一下。我的editor要分成两个部分,一边是TreeView, 一边是显示节点和连线,就好像是把大纲视图嵌入到了editor里。因为他们分别显示不同的部分,又一一对应。你有没有这方面的例子?我如何才能实现他们呢?

多谢指教
  回复  引用    

#9楼 [楼主] 2005-08-08 20:15 八进制      
应该是继承GraphicalEditorWithFlyoutPalette来实现,覆盖其中的createPartControl()方法把“大纲”加进去,但肯定还有其他工作要做,比如选择的同步等等,感觉会很麻烦。不如利用perspective把大纲加在Editor的旁边,如果允许的话。
  回复  引用  查看    

#10楼  2005-08-10 01:44 lucia [未注册用户]
非常感谢,

我试过把大纲通过覆盖createPartControl()的方法加进去,可是没有成功。我不知道错在哪里,因为没有任何出错信息,但也没有任何显示。第二个建议是比较简单,可是我要建立的是一个gantt chart, 大纲显示的是任务,我的理想是把大纲嵌入其中。我现在有个折中的办法,就是任务不用树形结构表示,也是用节点。可问题也不小,如何在浏览的时候,将任务节点保持不动,我还没有一点头绪呢。如果你有什么建议,将感激不尽。


  回复  引用    

#11楼  2005-08-10 18:30 panda [未注册用户]
Does it work GefPractice with eclipse 3.1 and gef 3.1?
Thank you.
  回复  引用    

#12楼 [楼主] 2005-08-10 20:39 八进制      
lucia:gantt图很麻烦,上一个项目里我们组的大牛花了不少功夫,基本是用draw2d自己实现的。
panda:GefPractice在eclipse 3.1里运行不起来。
  回复  引用  查看    

#13楼  2005-08-10 22:53 lucia [未注册用户]
八进制:
可惜是我的毕业论文,没得选择了,必须完成。我就是觉得用draw2d自己实现实在太麻烦,所以才用gef的。原来打算抄写ganttproject的开源码,可是读那些没有注释的code太头痛,要改的东西太多,才开始另起炉灶的。我实在没有把握,能不能在一个月内编完。因为这只是一部分。

  回复  引用    

#14楼  2005-08-11 06:02 lucia [未注册用户]
打扰了,我能再提个问题吗?

我才注意到,EditPart里的getModelChildren只能返回一种类型的children吗?如果我的模型有的元素有很多类型的children,那该怎么办呢?多谢指点.
  回复  引用    

#15楼 [楼主] 2005-08-11 11:37 八进制      
让这些children继承同一个父类
  回复  引用  查看    

#16楼  2005-08-11 14:26 lucia [未注册用户]
谢谢你的解答。
  回复  引用    

#17楼  2005-08-11 17:25 panda [未注册用户]
Thx for your answer yesterday.
Now i have eclipse 3.0.1 and gef 3.0.1.
I downloded GefPractice.
I did:
file->import->existingtoworkspace
run as eclipse workbench
in the new eclipse instance
file->new->simple project->"gefprac"
gefprac->new->file->"gefp.gef"

But it doesn't work. So something goes wrong.

Could you advice me how i can run gefpractice?

Thank you.

  回复  引用    

#18楼 [楼主] 2005-08-11 19:26 八进制      
Your file should be named "gefp.gefpractice", not "gefp.gef".
  回复  引用  查看    

#19楼  2005-08-11 23:55 panda [未注册用户]
Thank you. It works.
  回复  引用    

请教八进制,如何给FreeformLayeredPane 加一个居中的背景图片 ,
FreeformLayeredPane中有FreeformLayer
谢谢!
  回复  引用    

#21楼 [楼主] 2005-08-15 20:33 八进制      
给FreeformLayeredPane加一个新层,在这个新层上画背景图。
  回复  引用  查看    

#22楼  2005-08-16 02:41 lucia [未注册用户]
freegoldlu, 八进制,

另一种可能性,建立一个新的class,继承FreeformLayer,覆盖paintClientArea方法,在这里加入你的背景图案。我就是这么做的。




  回复  引用    

#23楼  2005-08-20 06:54 lucia [未注册用户]
有关上次EditPart里的getModelChildren只能返回一种类型的children的问题,想再问一下, 让这些children继承同一个父类,可是如果这些children是用不同editpart控制的,怎么办呢?谢谢
  回复  引用    

#24楼 [楼主] 2005-08-20 15:58 八进制      
在你的EditPartFactory里根据不同子类返回需要的EditPart,不知道你问的是不是这个问题呢?
  回复  引用  查看    

#25楼  2005-08-21 01:51 lucia [未注册用户]

答案找到了,getModelChildren的时候可以将不同类型的children将入到一个list里,就行了。

我一开始在处理list的时候,没有新建,而是
List list = getModel().getChildBs();
list.addAll(getModel().getChildCs());
糊涂啊,改成
List list =new ArrayList(getModel.getChildBs());
list.addAll(getModel().getChildCs());
就行了。

浪费了大家很多时间帮我找错,真是不安啊。

多谢了
  回复  引用    

#26楼  2005-09-09 15:12 tutufool [未注册用户]
请问,如果我需要在editor中的node上面doubleclick,然后进行相应的操作,比如探出对话框,这种行为需要在哪里实现,是在editpart里面么

  回复  引用    

#27楼  2005-09-09 15:41 tutufool [未注册用户]
找到了,覆盖AbstractEditPart.performRequest(Request req)
哎,感觉抽象结构太复杂也不太好啊,找起来费劲:(

  回复  引用    

#28楼  2005-09-09 23:05 tutufool [未注册用户]
你好,我想请教一个关于模型持久化的问题
我想在我的项目中把gef的模型保存为一个xml文件
如果我在dom树中间增加一个节点,然后重新保存这个dom树
有没有办法保持原来xml文件的结构不被破坏,假设我原来的xml文件是ctrl+shift+f过的,就好像是我手动在文件中添加了一个element在末尾一样。
我在GEF的eDiagram的例子里面看到它用的好像是XMIResouceImpl之类的东东,保存出来的ecore模型好像格式很工整,但这个eDiagram的model部分好像是用EMF做的,没看明白,不知道内存中的model怎么反映到resource上去的。

  回复  引用    

#29楼 [楼主] 2005-09-10 22:34 八进制      
大部分xml api都有格式化的功能吧,保存的时候先格式化一下得到的结果应该就是工整的。
  回复  引用  查看    

#30楼  2005-09-11 08:35 xiaohua [未注册用户]
请问tutufool 和八进制
1。如何 将gef的模型保存为一个xml文件?能不能稍微详细点说一下?谢谢

2。是否可以在网页中图形化的显示编辑的这个模型?比如在一个网页的frame中显示出来?

3。我在运行例子时候,新建模型编辑时其中的节点的属性选项一直不能显示,大概会是什么原因?谢谢

  回复  引用    

#31楼 [楼主] 2005-09-11 13:21 八进制      
1、利用xml包手动保存,或利用对象-xml映射工具如castor、xmlobject。
2、可以输出为png或jpg等格式显示在网页里。
3、只要模型实现了IPropertySource并且在getPropertyDescriptors方法里返回了正确的数组就应该有显示,如果仍然不能显示要看报什么异常了。
  回复  引用  查看    

#32楼  2005-09-22 17:54 Jackey [未注册用户]
你好。你上面提供的例子的下载地址下载不了了哟。可不可以麻烦发一份到我的邮箱jackeyjw@163.com,或者更新一下上面的链接。谢谢。

  回复  引用    

#33楼 [楼主] 2005-09-22 22:46 八进制      
刚试了一下,可以下载啊。http://www.cnblogs.com/bjzhanghao/Files/bjzhanghao/gefpractice31.zip
  回复  引用  查看    

#34楼  2005-09-23 10:19 Jackey [未注册用户]
太郁闷了。我怎么下载不了呀。总是报下面的错误。

.Text - Application Error!
Details

Resource not found

  回复  引用    

#35楼  2005-09-25 06:01 panda [未注册用户]
How to see Property window? thanks
  回复  引用    

#36楼  2005-09-25 06:18 panda [未注册用户]
ok, i've found it.
  回复  引用    

#37楼  2005-09-26 13:49 sean [未注册用户]
八进制,你好!又遇到了一个奇怪的问题,是关于Connection的。不知道放在哪个帖子好,就先放这个吧,因为这个帖子的例子里正有这样的问题。
好了,还是说说我的问题吧。当我们在做GEF的时候,connection是个比较特殊的东西,为什么呢?当把Node删除,那么Connection呢?是直接删除还是保留呢?我们通常是和Node一起删掉。但是如果不删掉呢?--你就会发现,删掉的如果是connection的target,你可以选中connection,并且还能拖动,如果你删掉的是source,这个Connection就会出现奇怪的现象。不能reconnect了。而且选中了,SelectionHandles也显示不出来。
为了解决这个问题。我单步跟踪了删除Node的操作,发现EditPart对souceConnection和targetConnection的处理是不同的。
protected void removeSourceConnection(ConnectionEditPart connection) {
fireRemovingSourceConnection(connection, getSourceConnections().indexOf(connection));
if (connection.getSource() == this) {
connection.deactivate();
connection.setSource(null);
}
primRemoveSourceConnection(connection);
}
protected void removeTargetConnection(ConnectionEditPart connection) {
fireRemovingTargetConnection(connection, getTargetConnections().indexOf(connection));
if (connection.getTarget() == this)
connection.setTarget(null);
primRemoveTargetConnection(connection);
}
处理sourceConnection的时候,有connection.deactivate();而处理targetConnection的时候就没有。而且
protected void addSourceConnection(ConnectionEditPart connection, int index) {
primAddSourceConnection(connection, index);
connection.setSource(this);
if (isActive())
connection.activate();
fireSourceConnectionAdded(connection, index);
}
这里只管connection.activate();而不去管connection本身是不是active的。
所以我就针对以上的问题,做了修改,将removeSourceConnection中的dactive去掉了。然后,在connection做activate的时候检查connection的状态。
这样修改以后,是没有出现SourceNode删除后产生问题了,但是,这样做,会不会造成connection不能被dactivate()或者导致内存泄漏呢?我有点晕?望指教
  回复  引用    

#38楼  2005-09-26 13:57 sean [未注册用户]
这里是我做的修改:
protected void removeSourceConnection(ConnectionEditPart connection) {
fireRemovingSourceConnection(connection, getSourceConnections().indexOf(connection));
if (connection.getSource() == this) {
connection.setSource(null);
if(connection.getTarget()==null){
connection.deactivate();
}
}
primRemoveSourceConnection(connection);
}

protected void removeTargetConnection(ConnectionEditPart connection) {
fireRemovingTargetConnection(connection, getTargetConnections().indexOf(connection));
if (connection.getTarget() == this){
connection.setTarget(null);
if(connection.getSource()==null){
connection.deactivate();
}
}
primRemoveTargetConnection(connection);
}

Connection的activate()
public void activate() {
if(!isActive()){
super.activate();
getElement().addPropertyChangeListener(this);
}
}
  回复  引用    

#39楼  2005-09-28 04:11 jx [未注册用户]
I can't download the example either. Is the link broken?

Thanks
  回复  引用    

#40楼  2005-09-28 06:05 panda [未注册用户]
Hi,
I wonder how gef (flow example) save the diagram realized by user. Could indicate me the class concerned.

  回复  引用    

#41楼 [楼主] 2005-09-28 21:56 八进制      
链接已经修好了,请再试试。
flow我还没看,应该在editor的doSaveAs()里找吧。
  回复  引用  查看    

#42楼  2005-09-29 04:18 jx [未注册用户]
Yes, it works fine now. Thanks.
I just noticed you attended the exteme blue program in IBM china this year. I attended the same program in IBM Canada.
  回复  引用    

#43楼  2005-10-10 18:35 yejianhui [未注册用户]
我想用GEF做一个网页编辑器,能脱离eclipse平台使用GEF吗?
  回复  引用    

#44楼 [楼主] 2005-10-10 22:50 八进制      
可以,虽然会比较麻烦。另外你也可以用rcp实现。
  回复  引用  查看    

#45楼 [楼主] 2005-10-10 22:57 八进制      
jx: So glad to see you here! We have just finished the program last month, very interesting and fruitful. Are you Chinese? We could have a talk on msn, my id is bjzhanghao at hotmail dot com.
  回复  引用  查看    

#46楼  2005-10-11 09:24 yejianhui [未注册用户]
自己的RCP里使用GEF,网上从来没有人这样用过吗?
  回复  引用    

#47楼  2005-10-11 16:17 zlc [未注册用户]
八进制:
你好。请教一下。我正在做一个GEF项目,遇到了一个问题:我想获得Palette中的比如node的Location,但这个Location必须是以一个固定的Editor(空白画布)大小为依据获得的值。举例说,假定现在我的Editor(空白画布)是600*400的(我是模拟现实的一个LCD显示屏大小),则当我拖动一个node到空白画布,那么我要获得它的Location(为了与现实的显示屏相似,这个Location值必须是在600*400中对应的值)。该怎么在程序中实现呢?谢谢!:)
  回复  引用    

#48楼 [楼主] 2005-10-11 16:58 八进制      
不是太明白你的意思,“要得到palette中node的location”,是指得到node对应的那个toolentry在palette里的位置?画布的大小可以指定为固定值,取决于content的figure。
  回复  引用  查看    

#49楼  2005-10-11 17:37 zlc [未注册用户]
不好意思,是我没讲清楚。
我现在用GEF实现的Editor是有3部分:调色板、GraphicalEditorViewer(空白画布——这是模拟LCD显示屏的)以及CodeEditorViewer(代码编辑区)。有点像Visual Editor。调色板内我自定了几种工具,Button之类。现在的问题是当我拖一个Button在画布里,那么它在画布中的Location的值我想与现实中LCD显示屏一致。可以实现吗?
谢谢!
  回复  引用    

#50楼 [楼主] 2005-10-11 20:58 八进制      
可以吧,你拖过去的button的位置就是以画布左上角为坐标原点,在你生成的代码里使用这个坐标值就对了。
  回复  引用  查看    

#51楼  2005-10-11 21:56 zlc [未注册用户]
谢谢!
很高兴当我开始要学GEF时候,在网上看到了你的一系列关于GEF入门文章。可能你难以想象它们对我的帮助有多么大!真的很感谢你的指引!要继续为人民服务而加油呵
:)
  回复  引用    

#52楼  2005-10-11 22:57 baal [未注册用户]
我是今天才开始学习GEF,看了你的文章对我的帮助很大。
但现在遇到一个问题。我需要在RCP程序中使用GEF。但我参照你的实例移植的时候在创建editpart的时候出现下面的错误。不知道如何解决。
java.lang.ExceptionInInitializerError
at org.eclipse.gef.ui.parts.GraphicalEditorWithPalette.createPaletteViewer(GraphicalEditorWithPalette.java:51)
at org.eclipse.gef.ui.parts.GraphicalEditorWithPalette.createPartControl(GraphicalEditorWithPalette.java:64)
at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:585)
at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:365)
at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:552)
at org.eclipse.ui.internal.PartPane.setVisible(PartPane.java:283)
at org.eclipse.ui.internal.presentations.PresentablePart.setVisible(PresentablePart.java:126)
at org.eclipse.ui.internal.presentations.util.PresentablePartFolder.select(PresentablePartFolder.java:268)
at org.eclipse.ui.internal.presentations.util.LeftToRightTabOrder.select(LeftToRightTabOrder.java:65)
at org.eclipse.ui.internal.presentations.util.TabbedStackPresentation.selectPart(TabbedStackPresentation.java:391)
at org.eclipse.ui.internal.PartStack.refreshPresentationSelection(PartStack.java:1102)
at org.eclipse.ui.internal.PartStack.setSelection(PartStack.java:1051)
at org.eclipse.ui.internal.PartStack.showPart(PartStack.java:1256)
at org.eclipse.ui.internal.PartStack.add(PartStack.java:442)
at org.eclipse.ui.internal.EditorStack.add(EditorStack.java:109)
at org.eclipse.ui.internal.EditorSashContainer.addEditor(EditorSashContainer.java:60)
at org.eclipse.ui.internal.EditorAreaHelper.addToLayout(EditorAreaHelper.java:212)
at org.eclipse.ui.internal.EditorAreaHelper.addEditor(EditorAreaHelper.java:202)
at org.eclipse.ui.internal.EditorManager.createEditorTab(EditorManager.java:753)
at org.eclipse.ui.internal.EditorManager.openEditorFromDescriptor(EditorManager.java:665)
at org.eclipse.ui.internal.EditorManager.openEditor(EditorManager.java:628)
at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2323)
at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2258)
at org.eclipse.ui.internal.WorkbenchPage.access$9(WorkbenchPage.java:2250)
at org.eclipse.ui.internal.WorkbenchPage$9.run(WorkbenchPage.java:2236)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:69)
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2231)
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2212)
at com.motos.gef.ApplicationWorkbenchWindowAdvisor.postWindowOpen(ApplicationWorkbenchWindowAdvisor.java:51)
at org.eclipse.ui.internal.WorkbenchWindow.fireWindowOpened(WorkbenchWindow.java:1070)
at org.eclipse.ui.internal.WorkbenchWindow.open(WorkbenchWindow.java:701)
at org.eclipse.ui.internal.Workbench.busyOpenWorkbenchWindow(Workbench.java:677)
at org.eclipse.ui.internal.Workbench.doOpenFirstTimeWindow(Workbench.java:1282)
at org.eclipse.ui.internal.Workbench.openFirstTimeWindow(Workbench.java:1223)
at org.eclipse.ui.internal.WorkbenchConfigurer.openFirstTimeWindow(WorkbenchConfigurer.java:190)
at org.eclipse.ui.application.WorkbenchAdvisor.openWindows(WorkbenchAdvisor.java:706)
at org.eclipse.ui.internal.Workbench.init(Workbench.java:1034)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:1636)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:367)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:143)
at com.motos.gef.Application.run(Application.java:18)
at org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:226)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:376)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:163)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.core.launcher.Main.invokeFramework(Main.java:334)
at org.eclipse.core.launcher.Main.basicRun(Main.java:278)
at org.eclipse.core.launcher.Main.run(Main.java:973)
at org.eclipse.core.launcher.Main.main(Main.java:948)
Caused by: java.lang.NullPointerException
at org.eclipse.gef.ui.palette.DefaultPaletteViewerPreferences.<init>(DefaultPaletteViewerPreferences.java:62)
at org.eclipse.gef.ui.palette.PaletteViewer.<clinit>(PaletteViewer.java:89)
... 52 more

希望你能帮忙。谢谢!!

  回复  引用    

#53楼  2005-10-12 10:24 zlc [未注册用户]
你好,八进制!
还是昨天的问题。现在我就想把画布固定住(600*400),整个Editor肯定是可以放大缩小的,那怎么解决Palette调色板、空白画布和编码区三者的布局呢?要求就是画布要固定。你昨天提供的建议是在content figure中固定画布,能解释一下你说的content figure指的是什么啊??
谢谢!
  回复  引用    

#54楼 [楼主] 2005-10-12 15:12 八进制      
content figure就是你作为画布的那个figure,所有的节点都直接或间接放在这个画布上,这个figure是在rooteditpart的createFigure()方法里返回的。
  回复  引用  查看    

#55楼  2005-10-14 14:53 zlc [未注册用户]
不好意思,八进制
还得问一下,rooteditpart不就是两种吗?ScalableFreeformRootEditPart以及ScalableRootEditPart,无论哪一种,都是可以伸缩的呀(我采用的是前者),怎么固定啊。另外,我的程序中与代表整个图相对应的part为SchemaDiagramPart,它的createFigure()返回的是SchemaFigure,这是一个继承了FreeformLayer的图形。可以固定吗?怎么实现呢?
拜托了:)
  回复  引用    

#56楼 [楼主] 2005-10-14 22:36 八进制      
别让SchemaFigure继承FreeformLayer,继承Layer或者直接从Figure继承应该都可以。
  回复  引用  查看    

#57楼  2005-10-17 01:07 panda [未注册用户]
Hi,

I tried to write diagram in a file with dosave decribed in Flow. But gef gave exceptions when i close gefpractice instance: no written object. I spend a lot of time to find the problem but in vain. Could you some concret suggestions. Thx.
  回复  引用    

#58楼 [楼主] 2005-10-17 11:16 八进制      
panda, I'm afraid you have to paste the exception stack messages here.
  回复  引用  查看    

#59楼  2005-10-18 06:04 panda [未注册用户]
Hi,

Here are the exceptions mentionned:

java.io.NotSerializableException: org.eclipse.ui.views.properties.TextPropertyDescriptor
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeArray(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
...............................


and all those exceptions are generated by the code below

protected void createOutputStream(OutputStream os) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(os);
out.writeObject(this.diagram);
out.close();
}

public void doSave(IProgressMonitor monitor) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
createOutputStream(out);
IFile file = ((IFileEditorInput)getEditorInput()).getFile();
file.setContents(new ByteArrayInputStream(out.toByteArray()),
true, false, monitor);
out.close();
getCommandStack().markSaveLocation();
}
catch (Exception e) {
e.printStackTrace();
}
}

public void doSaveAs() {
}

  回复  引用    

#60楼 [楼主] 2005-10-18 09:45 八进制      
把类型为org.eclipse.ui.views.properties.TextPropertyDescriptor的成员变量标记为static或者transient就可以了,因为这种类型不支持序列化,即没有实现Serializable接口。
  回复  引用  查看    

#61楼  2005-10-18 20:29 panda [未注册用户]
Hi,

I did as you said. Now i have new message: "save all failed: org.eclipse.ui.part.FileEditorInput".

I imported then that class, but the same message persisted.

Sorry to bother you. I am beginner in Gef and your help is very precious.




  回复  引用    

#62楼  2005-10-19 05:34 panda [未注册用户]
Sorry, the previous message is not valid.

I did as you said (and refered flow code), now I think things are going better, but there are still exceptions as below

java.lang.ClassCastException
at com.example.ui.PracticeEditor.doSave(PracticeEditor.java:88)
at org.eclipse.ui.internal.EditorManager$6.run(EditorManager.java:1121)
at org.eclipse.ui.internal.SaveableHelper$2.run(SaveableHelper.java:116)
at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:346)
at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:291)
at org.eclipse.jface.window.ApplicationWindow$1.run(ApplicationWindow.java:624)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:69)
at org.eclipse.jface.window.ApplicationWindow.run(ApplicationWindow.java:621)
at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2134)

.....................................
  回复  引用    

#63楼 [楼主] 2005-10-19 12:12 八进制      
在PracticeEditor.java第88行设置断点看看是哪里ClassCastException,这个问题很容易找到的。
  回复  引用  查看    

#64楼  2005-10-20 22:01 wooood [未注册用户]
八进制, 你好

我是按照你的GetPractice例子一点一点在学Gef

我在NodePart的createEditPolicies方法里面也增加了
installEditPolicy(EditPolicy.COMPONENT_ROLE, new NodeEditPolicy());

但是我在按键盘上的delete健时,就是删除不了node

不知道是怎么回事
  回复  引用    

#65楼  2005-10-20 23:59 wooood [未注册用户]
我找到原因了

是因为我把ActionBar都去掉了

难道只能覆盖ActionBarContributor的buildActions()方法才能注册

撤销、重复、删除这样的Action吗?
  回复  引用    

#66楼  2005-10-21 17:45 panda [未注册用户]
Hi,
I tried with debug as you said concered "doSave". But i have not got more detaile about the exceptions. All exceptions are generated by the line:

IFile file = ((IFileEditorInput)getEditorInput()).getFile();

No idea about this problem.

  回复  引用    

#67楼 [楼主] 2005-10-21 17:51 八进制      
getEditorInput()得到的不是IFileEditorInput,所以强制转换就报ClassCastException了。把断点设在这句,然后检查getEditorInput()看看是什么类型。
  回复  引用  查看    

#68楼  2005-10-22 06:50 panda [未注册用户]
Hi,
getEditorInput return EditorInput. I got even the id.
The code doSave is the same as in example Flow. I wonder if there is some thing from Node does not adapte
IFile file = ((IFileEditorInput)getEditorInput()).getFile();
I will compare Flow and gefpractice, that's what i can do now.

Thanks anyway for your answers. If you code doSave, please show me how it works.

See you
  回复  引用    

#69楼 [楼主] 2005-10-24 21:48 八进制      
IEditorInput的实现不一定能转成IFileEditorInput的
  回复  引用  查看    

#70楼  2005-10-25 05:29 panda [未注册用户]
I agree with you. I think the contruction of model (Node.java) doesn't adapte to the method doSave. (just an idea, nothing concrete).
  回复  引用    

#71楼  2005-10-25 20:30 panda [未注册用户]
That's ok. A problem of dependency. I found it by reading your blog. Thx.
  回复  引用    

#72楼  2005-10-26 09:40 zlc [未注册用户]
你好,八进制!
不好意思,又得麻烦你了:)
我想向你请教一个问题:你有没有遇到这种情况啊----依然是有关Editor的问题,有一个Button在空白画布上,当我把它拖向调色板一侧,并且靠近调色板与空白画布之间的“|“(分界?),Button就自己跑向左侧(看起来),直至空白画布的水平滚动条急速移至左最右端(实际上是空白画布的水平滚动条急速右移)。这是什么导致的呢?可以解决吗?
谢谢你的帮忙!

  回复  引用    

#73楼  2005-11-14 23:04 panda [未注册用户]
tutufool,

You have asked " 请问,如果我需要在editor中的node上面doubleclick,然后进行相应的操作,比如探出对话框,这种行为需要在哪里实现,是在editpart里面么 " and you've found the solution.

Could you show me how you do it concretely (better with code).

八进制,

If you know that, could you answer me (tutufool maybe don't view my message).

Thank you.


  回复  引用    

#74楼  2005-11-17 11:01 zxw [未注册用户]
八进制你好!
我定义了一个sourceEditor继承了textEditor类,
并且implements MouseListener,
现在我想给这个sourceEditor添加MouseListener,
但是我发现它下面没有addMouseListener这个方法,只有addPropertyListener方法。
给这个sourceEditor创建鼠标监听器大概都需要做哪些工作??
  回复  引用    

#75楼  2005-12-09 10:56 mercury [未注册用户]
八进制,请教个问题
我做了个PLUG_IN,在测试的时候,都会出现“Unable to create this part due to an internal error. Reason for the failure: The editor class could not be instantiated. This usually indicates that the editor's class name was mistyped in plugin.xml.”的错误。
其中“MyEditor”是我的editor
我检查了,在plugin.xml里我的editor名字是正确的。

还有什么情况会导致上述错误呢!
非常紧急谢谢!
PS 由于长度限制,详细信息在下面一个帖子内。
  回复  引用    

#76楼  2005-12-09 10:57 mercury [未注册用户]
详细信息如下:
java.lang.ClassNotFoundException: com.test.mercury.ui.MyEditor
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:403)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:350)
at org.eclipse.osgi.framework.adaptor.core.AbstractClassLoader.loadClass(AbstractClassLoader.java:78)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.eclipse.osgi.framework.internal.core.BundleLoader.loadClass(BundleLoader.java:275)
at org.eclipse.osgi.framework.internal.core.BundleHost.loadClass(BundleHost.java:227)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadClass(AbstractBundle.java:1259)
at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:152)
at org.eclipse.core.internal.regis