八进制

少年壮志无烟抽

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

虽然很多GEF应用程序里都会用到连接(Connection),但也有一些应用是不需要用连接来表达关系的,我们目前正在做的这个项目就是这样一个例子。在这类应用中,模型对象间的关系主要通过图形的包含来表达,所以大多是一对多关系。

cbm1.gif
图1 不使用连接的GEF应用

先简单描述一下我们这个项目,该项目需要一个图形化的模型编辑器,主要功能是在一个具有三行N列的表格中自由增加/删除节点,节点可在不同单元格间拖动,可以合并相邻节点,表格列可增减、拖动等等。由于SWT/Jface提供的表格很难实现这些功能,所以我们选择了使用GEF开发,目前看来效果还是很不错的(见下图),这里就简单介绍一下实现过程中与图形和布局有关的一些问题。

在动手之前首先还是要考虑模型的构造。由于Draw2D只提供了很有限的Layout,如ToolbarLayout、FlowLayout和XYLayout,并没有一个GridLayout,所以不能把整个表格作为一个EditPart,而应该把每一列看作一个EditPart(因为对列的操作比对行的操作多,所以不把行作为EditPart),这样才能实现列的拖动。另外,从需求中可以看出,每个节点都包含在一个列中,但仔细再研究一下会发现,实际上节点并非直接包含在列中,而是有一个单元格对象作为中间的桥梁,即每个列包含固定的三个单元格,每个单元格可以包含任意个节点。经过以上分析,我们的模型、EditPart和Figure应该已经初步成形了,见下表:

 

模型

EditPart

Figure

画布

Diagram

DiagramPart

FreeformLayer

Column

ColumnPart

ColumnFigure

单元格

Cell

CellPart

CellFigure

节点

Node

NodePart

NodeFigure

表中从上到下是包含关系,也就是一对多关系,下图简单显示了这些关系:

cbm2.gif
图2 图形包含关系图

让我们从画布开始考虑。在画布上,列显示为一个纵向(高大于宽)的矩形,每个列有一个头(Header)用来显示列名,所有列在画布上是横向排列的。因此,画布应该使用ToolbarLayout或FlowLayout中的一种。这两种Layout有很多相似之处,尤其它们都是按指定的方向排列显示图形,不同之处主要在于:当图形太多容纳不下的时候,ToolbarLayout会牺牲一些图形来保持一行(列),而FlowLayout则允许换行(列)显示。

对于我们的画布来说,显然应该使用ToolbarLayout作为布局管理器,因为它的子图形ColumnFigure是不应该出现换行的。以下是定义画布图形的代码:

Figure f = new FreeformLayer();
ToolbarLayout layout
=new ToolbarLayout();
layout.setVertical(
false);
layout.setSpacing(
5);
layout.setStretchMinorAxis(
true);
f.setLayoutManager(layout);
f.setBorder(
new MarginBorder(5));

其中setVertical(false)指定横向排列子图形,setSpacing(5)指定子图形之间保留5象素的距离,setStretchMinorAxis(true) 指定每个子图形的高度都保持一致。

ColumnFigure的情况要稍微复杂一些,因为它要有一个头部区域,而且它的三个子图形(CellFigure)合在一起要能够充满下部区域,并且适应其高度的变化。一开始我用Draw2D提供的Label来实现列头,但有一个不足,那就是你无法设置它的高度,因为Label类覆盖了Figure的getPreferedSize()方法,使得它的高度只与里面的文本有关。解决方法是构造一个HeaderFigure,让它维护一个Label,设置列头高度时实际设置的是HeaderFigure的高度;或者直接让HeaderFiguer继承Label并重新覆盖getPreferedSize()也可以。我在项目里使用的是前者。

第二个问题花了我一些时间才搞定,一开始我是在CellPart的refreshVisuals()方法里手动设置CellFigure的高度为ColumnFigure下部区域高度的三分之一,但这样很勉强,而且还需要额外考虑spacing带来的影响。后来通过自定义Layout的方式比较圆满的解决了这个问题,我让ColumnFigure使用自定义的ColumnLayout,这个Layout继承自ToolbarLayout,但覆盖了layout()方法,内容如下:

class ColumnLayout extends ToolbarLayout {
    public 
void layout(IFigure parent) {
        IFigure nameFigure
=(IFigure)parent.getChildren().get(0);
        IFigure childrenFigure
=(IFigure)parent.getChildren().get(1);
        Rectangle clientArea
=parent.getClientArea();
        nameFigure.setBounds(
new Rectangle(clientArea.x,clientArea.y,clientArea.width,30));
        childrenFigure.setBounds(
new Rectangle(clientArea.x,nameFigure.getBounds().height+clientArea.y,clientArea.width,clientArea.height-nameFigure.getBounds().height));
    }
}

也就是说,在layout里控制列头和下部的高度分别为30和剩下的高度。但这还没有完,为了让单元格正确的定位在表格列中,我们还要指定列下部图形(childrenFigure)的布局管理器,因为实际上单元格都是放在这个图形里的。前面说过,Draw2D并没有提供一个像SWT中FillLayout那样的布局管理器,所以我们要再自定义另一个layout,我暂时给它起名为FillLayout(与SWT的FillLayout同名),还是要覆盖layout方法,如下所示(因为用了transposer所以horizontal和vertical两种情况可以统一处理,这个transposer只在horizontal时才起作用):

public void layout(IFigure parent) {
    List children 
= parent.getChildren();
    
int numChildren = children.size();
    Rectangle clientArea 
= transposer.t(parent.getClientArea());
    
int x = clientArea.x;
    
int y = clientArea.y;
    
for (int i = 0; i < numChildren; i++) {
        IFigure child 
= (IFigure) children.get(i);
        Rectangle newBounds 
= new Rectangle(x, y, clientArea.width, -1);

        
int divided = (clientArea.height - ((numChildren - 1* spacing)) / numChildren;
        
if (i == numChildren - 1)
            divided 
= clientArea.height - ((divided + spacing) * (numChildren - 1));
        newBounds.height 
= divided;
        child.setBounds(transposer.t(newBounds));
        y 
+= newBounds.height + spacing;
    }
}

上面这些语句的作用是将父图形的高(宽)度平均分配给每个子图形,如果是处于最后的一位的子图形,让它占据所有剩下的空间(防止除不尽的情况留下空白)。完成了这个FillLayout,只要让childrenFigure使用它作为布局管理器即可,下面是ColumnFigure的大部分代码,列头图形(HeaderFigure)和列下部图形(ChildrenFigure)作为内部类存在:

private HeaderFigure name = new HeaderFigure();
private ChildrenFigure childrenFigure 
= new ChildrenFigure();
public ColumnFigure() {
    ToolbarLayout layout 
= new ColumnLayout();
    layout.setVertical(
true);
    layout.setStretchMinorAxis(
true);
    setLayoutManager(layout);
    setBorder(
new LineBorder());
    setBackgroundColor(color);
    setOpaque(
true);
    add(name);
    add(childrenFigure);
    setPreferredSize(
100-1);
}
class ChildrenFigure extends Figure {
    public ChildrenFigure() {
        ToolbarLayout layout 
= new FillLayout();
        layout.setMinorAlignment(ToolbarLayout.ALIGN_CENTER);
        layout.setStretchMinorAxis(
true);
        layout.setVertical(
true);
        layout.setSpacing(
5);
        setLayoutManager(layout);
    }
}
class HeaderFigure extends Figure {
    private String text;
    private Label label;
    public HeaderFigure() {
        
this.label = new Label();
        
this.add(label);
        setOpaque(
true);
    }
    public String getText() {
        
return this.label.getText();
    }
    public Rectangle getTextBounds() {
        
return this.label.getTextBounds();
    }
    public 
void setText(String text) {
        
this.text = text;
        
this.label.setText(text);
        
this.repaint();
    }
    public 
void setBounds(Rectangle rect) {
        super.setBounds(rect);
        
this.label.setBounds(rect);
    }
}

单元格的布局管理器同样使用FillLayout,因为在需求中,用户向单元格里添加第一个节点时,该节点要充满单元格;当单元格里有两个节点时,每个节点占二分之一的高度;依次类推。下面的表格总结了各个图形使用的布局管理。由表可见,只有包含子图形的那些图形才需要布局管理器,原因很明显:布局管理器关心和管理的是"子"图形,请时刻牢记这一点。

 

布局管理器

直接子图形

画布

ToolbarLayout

ColumnLayout

列头部、列下部

-列头部

-列下部

FillLayout

单元格

单元格

FillLayout

节点

节点

这里需要特别提醒一点:在一个图形使用ToolbarLayout或子类作为布局管理器时,图形对应的EditPart上如果安装了FlowLayoutEditPolicy或子类,你可能会得到一个ClassCastException异常。例如例子中的CellFigure,它对应的EditPart是CellPart,其上安装了CellLayoutEditPolicy是FlowLayoutEditPolicy的一个子类。出现这个异常的原因是在FlowLayoutEditPolicy的isHorizontal()方法中会将图形的layout强制转换为FlowLayout,而我们使用的是ToolbarLayout。我认为这是GEF的一个疏忽,因为作者曾说过FlowLayout可应用于ToolbarLayout。幸好解决方法也不复杂:在你的那个EditPolicy中覆盖isHorizontal()方法,在这个方法里先判断layout是ToolbarLayout还是FlowLayout,再根据结果返回合适的boolean值即可。

最后,关于我们的画布还有一个问题没有解决,我们希望表格列增多到一定程度后,画布可以向右边扩展尺寸,前面说过画布使用的是FreeformLayer作为图形。为了达到目的,还必须在editor里设置rootEditPart为ScalableRootEditPart,要注意不是ScalableFreeformRootEditPart,后者在需要各个方向都能扩展的画布的应用程序中经常被使用。关于各种RootEditPart的用法,在后续帖子里将会介绍到。

以上结合具体实例讲解了如何在GEF中使用ToolbarLayout以及自定义简单的布局管理器。我们构造图形应该遵守一个原则,那就是尽量让布局管理器决定每个子图形的位置和尺寸,这样可以避免很多麻烦。当然也有例外,比如在XYLayout这种只关心子图形位置的布局管理器中,就必须为每个子图形指定尺寸,否则图形将因为尺寸过小而不可见,这也是一个开发人员十分容易疏忽的地方。

posted on 2005-03-24 00:23 八进制 阅读(7564) 评论(61)  编辑 收藏 所属分类: EclipseGEF

评论

#1楼  2005-03-24 14:43 wb [未注册用户]
帖子更新挺快的,昨天晚上看到四,今天到五了!谢谢楼主,你的帖子对我帮助挺大的,期待你后续更精彩的帖子。
  回复  引用    

#2楼 [楼主] 2005-03-25 14:06 八进制      
谢谢支持,很高兴能帮到你。这个系列的确花了我不少时间,每篇都需要一段时间来构思。
另外,如果希望看到哪方面的内容也可以提出来。
  回复  引用  查看    

#3楼  2005-03-26 02:32 antaoran [未注册用户]
八进制,你好!请问,如果要改变第三篇例子中node的大小,应该怎么实现呢?我添加了几个类,但是在应该使用哪种editpolicy来处理请求的时候遇到了困难,是不是因为这个原因不能成功呢?
  回复  引用    

#4楼  2005-03-26 12:27 howjay [未注册用户]
应该用一个extends XYLayoutEditPolicy的EditPplicy类吧,里面调用createChangeConstraintCommand返回ChangeConstraintCommand(自己定义的)的实例
  回复  引用    

#5楼 [楼主] 2005-03-27 15:20 八进制      
exactly
  回复  引用  查看    

#6楼  2005-03-27 18:55 yes [未注册用户]
八进制,你好!我下载了你的GefPractice的源代码,然后导入eclipse中 但是有一个地方报错了 提示如下:
"不能解析类型 org.eclipse.ui.views.contentoutline.IContentOutlinePage。从必需的 .class 文件间
接引用了它”
不知道这是怎么一回事?
这个错误好像在howjay的评论中也提到过,但没有具体的解决方法(我装的是gef sdk)如果howjay兄已经解决了这个问题,麻烦告诉我解决办法,不胜感激!

  回复  引用    

#7楼 [楼主] 2005-03-27 21:01 八进制      
你的Eclipse版本是3.0以上吗,检查plugin.xml里是否有对org.eclipse.ui.views的依赖。
  回复  引用  查看    

#8楼  2005-03-27 21:06 howjay [未注册用户]
如果是3.0以上的话,尝试再在项目的“属性”-“JAVA构建路径”-”库“-”添加外部jar“,添加ui.views.的其它几个包,如workbench之类的。可以看看把它们全部添加进去是不是还有错,我似乎就是这么解决的
  回复  引用    

#9楼  2005-03-27 21:51 yes [未注册用户]
谢谢2位高手的指点,那个红色错误已经解决:) 但是好像又出现了另外的一个问题:我在执行运行为/运行时工作台操作时,eclipse提示说有错误,问我要不要继续执行,我选择了是,结果运行后报错,错误日志如下:
!SESSION Sun Mar 27 21:51:18 CST 2005 ------------------------------------------
!ENTRY org.eclipse.core.launcher 4 0 三月 27, 2005 21:51:19.62
!MESSAGE Exception launching the Eclipse Platform:
!STACK
java.io.FileNotFoundException: G:\eclipse.properties (系统找不到指定的文件。)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:106)
at java.io.FileInputStream.<init>(FileInputStream.java:66)
at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:69)
at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:156)
at java.net.URL.openStream(URL.java:913)
at org.eclipse.core.launcher.Main.load(Main.java:1126)
at org.eclipse.core.launcher.Main.loadProperties(Main.java:1098)
at org.eclipse.core.launcher.Main.addBaseJars(Main.java:334)
at org.eclipse.core.launcher.Main.getDevPath(Main.java:286)
at org.eclipse.core.launcher.Main.getBootPath(Main.java:406)
at org.eclipse.core.launcher.Main.basicRun(Main.java:174)
at org.eclipse.core.launcher.Main.run(Main.java:704)
at org.eclipse.core.launcher.Main.main(Main.java:688)
我不知道问题出在哪里,还是要麻烦二位一下,不好意思.
ps:我用的eclipse是3.0.1
  回复  引用    

#10楼  2005-03-27 22:04 yes [未注册用户]
我刚才查了一下,好像我的eclipse的plugin文件夹里面少了org.eclipse.xsd.editor这个包
这要下哪个插件才行啊?
  回复  引用    

#11楼  2005-03-27 23:35 yes [未注册用户]
我刚才已经把org.eclipse.xsd.editor这个包放到plugins里面了 可是例子运行的时候还是报错:
找不到文件:'G:应用软件\eclipse\workspace\.metadata\.plugins\org.eclipse.pde.core\配置\1111937526906.log'
点击确定后就出来我上面贴的错误日志

不知道是怎么回事 是不是因为我把eclipse装在中文名路径下的缘故?
  回复  引用    

#12楼 [楼主] 2005-03-27 23:36 八进制      
从上面的异常来看,你的eclipse好象安装得有问题,用干净的eclipse再试试。org.eclipse.xsd.editor不是必要的。
  回复  引用  查看    

#13楼  2005-03-28 13:11 yes [未注册用户]
谢谢 问题已经解决 虽然还是提示项目存在错误 但是已经不影响程序的运行了
  回复  引用    

#14楼  2005-03-30 11:18 mlrain [未注册用户]
上面那位YES老兄,我也碰到了相同的问题,不知道你是怎么解决的?谢了!

我装了Eclipse的2.1.2和3.0.1。
  回复  引用    

#15楼  2005-03-30 12:07 mlrain [未注册用户]
现在换了个干净的Eclipse3.0.1,结果显示另外一个错误,完全的信息如下:

!SESSION 三月 30, 2005 11:53:23.132 ----------------------------------------------
eclipse.buildId=unknown
java.version=1.5.0-beta
java.vendor=Sun Microsystems Inc.
BootLoader constants: OS=win32, ARCH=x86, WS=win32, NL=zh_CN
Command-line arguments: -application org.eclipse.ui.ide.workbench -pdelaunch

!ENTRY org.eclipse.osgi 三月 30, 2005 11:53:23.132
!MESSAGE Application error
!STACK 1
java.lang.RuntimeException: Application "org.eclipse.ui.ide.workbench" could not be found in the registry. The applications available are: <NONE>.
at org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:325)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:273)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:129)
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.basicRun(Main.java:185)
at org.eclipse.core.launcher.Main.run(Main.java:704)
at org.eclipse.core.launcher.Main.main(Main.java:688)

!ENTRY org.eclipse.osgi 三月 30, 2005 11:53:23.152
!MESSAGE Bundle initial@reference:file:D:/My Works/Agree/ICBC/ISBP/Dev. Dir/test/gef-six-examples/HelloGef1/ [5] was not resolved.
!SUBENTRY 1 org.eclipse.osgi 三月 30, 2005 11:53:23.152
!MESSAGE Missing required bundle org.eclipse.core.runtime.compatibility_0.0.0.

  回复  引用    

#16楼 [楼主] 2005-03-30 14:37 八进制      
不好意思,以前的gefpractice.zip的plugin.xml里有些问题,dependencies部分应该是下面这样:
<import plugin="org.eclipse.core.resources"/>
<import plugin="org.eclipse.gef"/>
<import plugin="org.eclipse.ui"/>
<import plugin="org.eclipse.core.runtime"/>
<import plugin="org.eclipse.core.runtime.compatibility"/>
<import plugin="org.eclipse.ui.views"/>
原先最后一个是org.eclipse.xsd.editor,应该改为org.eclipse.ui.views才对,这个是大纲视图所需要的。gefpractice.zip我已重新上传,前文也已修改,谢谢YES和mlrain指出这个问题。
  回复  引用  查看    

#17楼  2005-03-30 21:45 faraway [未注册用户]
楼主的帖子对我的帮助很大,太感谢了!
我最近遇到了一个问题,我给很多model添加了一个属性页,在属性页中改变改变某些属性后,可以更新对应的model,但是如何让editor知道该model已经被修改过了呢?我看过其他例子中发现model的修改是通过command来实现的,command被使用后,就会触发commandstackchange()函数,这里面会firePropertyChange(IEditorPart.PROP_DIRTY)并以此来通知editor某些model已经被修改,但是这些都是直接在viewer上操作从而产生的command,那么如何修改属性页时也能产生类似的command呢?谢谢
  回复  引用    

#18楼 [楼主] 2005-03-31 14:31 八进制      
我试了一下,在properties view里改属性一样能触发commandstackchange(),gef好象注册了listener在celleditor里。
  回复  引用  查看    

#19楼  2005-03-31 21:45 faraway [未注册用户]
我也发现了,我估计可能是其他地方出问题了,不过还是非常感谢!期待后面会有更好的文章:)
  回复  引用    

#20楼  2005-05-19 06:23 不动 [未注册用户]
感谢你写的东西,对我帮助很大!
我通读了里面所有关于GEF的内容(包括问答)好象大家都没有提到过一个问题。
如何能从一个connectiton_A上面某一点(作为source)引出一条另外的connection_B,并且它的Target是另外一条connection_C上的某一点。
比如我现在所做的,用GEF做一个可以用于编辑电路图的项目。为了让图好看并且和传统电路图一样,比如说:在一个包含两个电阻的并联后在串上一个电阻的时候,就会出现这样的问题。

谢谢你的回答
  回复  引用    

#21楼 [楼主] 2005-05-20 21:37 八进制      
从Connection连接到Node节点或其他Connection从理论上来说是能实现的(我并没有实验过),你要定义一个继承AbstractConnectionEditPart和实现NodeEditPart的类,并且使用适合你需求的Anchor(现有的Anchor对线状图形似乎不合适),也就是把连接线当作一个节点来处理,也许还会遇到一些问题吧。
或者不从连接线出发,比如AB并联再串联C,可以让AB都直接连到C上,只是两条连接线的一部分是重合的,也能形成你要的效果,而且从模型上也说得通。用这种方法你要指定连接线的Router,可以试试ManhattanConnectionRouter或扩展它。
  回复  引用  查看    

#22楼  2005-06-06 21:28 peeker [未注册用户]
老大,请问这篇文章的代码有吗?多谢,again and again
  回复  引用    

#23楼 [楼主] 2005-06-06 23:27 八进制      
不好意思,由于涉及到正在做的项目,代码不方便提供。有任何问题可以直接问我,留言或email都可以的。
  回复  引用  查看    

#24楼  2005-09-02 13:56 sean [未注册用户]
最近用GEF,需要一个能自动换行的Label。当文字过长,能换行书写。怎么会不考虑这种情况呢?
  回复  引用    

#25楼 [楼主] 2005-09-02 16:29 八进制      
试试TextFlow
  回复  引用  查看    

#26楼  2005-09-21 15:26 sean [未注册用户]
用TextFlow其实简单,但是网络上的例子少,如果当作普通的Figure来用,是用不了的,一定要按规则放到指定容器里。我就是不知道该怎么用,走了很多弯路。现在把可以用的方法放在下面,这是一个自动换行的Label,比较粗陋。但比原来的好多了。
public class LabelEx extends FlowPage{
private TextFlow contents;
public WrapLabelEx(){
this("");
}
/**
*
*/
public LabelEx(String text) {
BlockFlow bl=new BlockFlow();
contents = new TextFlow();
//contents.setLayoutManager(new SimpleTextLayout(contents));
contents.setText(text);
bl.add(contents);
add(bl);
}
public void setText(String text){
contents.setText(text);
}
public String getText(){
return contents.getText();
}
}
  回复  引用    

#27楼  2005-09-21 15:29 sean [未注册用户]
这里是旧的实现,汗,大家不要笑我。
public class WrapLabel extends Label {
private String sourceText;
private boolean deal=false;
private int margin=20;
/**
*
*/
public WrapLabel() {
super();
this.sourceText="";
// TODO Auto-generated constructor stub
}

/**
* @param s
*/
public WrapLabel(String s) {
this.sourceText=s;
// TODO Auto-generated constructor stub
}
public WrapLabel(String s,int margin){
this.sourceText=s;
this.margin=margin;
}
/* (non-Javadoc)
* @see org.eclipse.draw2d.Label#setText(java.lang.String)
*/
public void setText(String s) {
this.sourceText=s;
deal=false;
}

/* (non-Javadoc)
* @see org.eclipse.draw2d.Label#paintFigure(org.eclipse.draw2d.Graphics)
*/
protected void paintFigure(Graphics graphics) {
modifyText();
super.paintFigure(graphics);
}
/* (non-Javadoc)
* @see org.eclipse.draw2d.Figure#setBounds(org.eclipse.draw2d.geometry.Rectangle)
*/
public void setBounds(Rectangle rect) {
deal=false;
super.setBounds(rect);
}
private void modifyText(){
if(deal) return;
Font f=getFont();
if(f != null){
int width = getBounds().width-margin;
StringBuffer buf=new StringBuffer();
if(width>5){
String str=sourceText;
while(str.length()>0){
int sub=getLargestSubstringConfinedTo(str,f,width);
if(sub==0 && str.length()>0) break;
if(sub< str.length()){
buf.append(str.substring(0,sub));
buf.append("\n");
str=str.substring(sub);
}
else{
buf.append(str);
str="";
}
}
}
deal=true;
super.setText(buf.toString());
}
}
private int getLargestSubstringConfinedTo(String s, Font f, int availableWidth) {
FontMetrics metrics = FigureUtilities.getFontMetrics(f);
int min, max;
float avg = metrics.getAverageCharWidth();
min = 0;
max = s.length() + 1;

//The size of the current guess
int guess = 0,
guessSize = 0;
while ((max - min) > 1) {
//Pick a new guess size
// New guess is the last guess plus the missing width in pixels
// divided by the average character size in pixels
guess = guess + (int)((availableWidth - guessSize) / avg);

if (guess >= max) guess = max - 1;
if (guess <= min) guess = min + 1;

//Measure the current guess
guessSize = FigureUtilities.getTextExtents(s.substring(0, guess), f).width;

if (guessSize < availableWidth)
//We did not use the available width
min = guess;
else
//We exceeded the available width
max = guess;
}
return min;
}
}

  回复  引用    

#28楼 [楼主] 2005-09-22 10:21 八进制      
谢谢sean的贡献:-)
  回复  引用  查看    

#29楼  2006-03-27 02:33 abent [未注册用户]
八进制,你好!
小弟在做GEF应用的时候碰到一个问题:
我想在画某个ParentModel时,在这个ParentModel中就已经存在几个固定的ChildModel了,于是我在ParentModel中创建了这些子ChildModel,然后ParentPart中也相应覆盖了getModelChildren()方法,但ParentPart的Figure画出来了之后却未看到ChildPart的Figure出现,是否少了什么步骤?

另外我想让这些ChildPart的Figure出现在ParentPart的Figure中的某个子Figure中,应该如何实现呢?
恳请八进制兄给小弟一些提示,谢谢!
  回复  引用    

#30楼 [楼主] 2006-03-27 15:19 八进制      
也许需要在editpart里手动refreshChildren()一下;
第二个问题应该覆盖getContentPane()方法。
  回复  引用  查看    

#31楼  2006-03-27 23:56 weller [未注册用户]
很感谢八进制的无私帮助. 请问CRM Editor的源码,我怎么也找不到的?请问在哪里啊?
  回复  引用    

#32楼 [楼主] 2006-03-31 22:13 八进制      
是说CBM Editor吗,抱歉这个代码无法提供下载。
  回复  引用  查看    

#33楼  2007-01-17 23:43 sion [未注册用户]
请问,

BorderLayout能用吗?如果可以,该如何将子模型加入个别的Panel (right, center, left, top, bottom)? 如果不可以,有没有类似的?

谢谢
  回复  引用    

#34楼  2007-01-22 23:43 xalix [未注册用户]
八进制,您好,

想请教你多一个问题,我在尝试制作类似CBM的一个程序,我希望得到一个效果,就是如果我双击 CBM Editor Tab 而扩大页面时,Column的宽度不更改,而高度则拉长至扩大后页面的高度,
然而,当我再双击 CBM Editor Tab, 而重新缩小时,我希望Column的高度也照样缩回来,而不是保留之前的高度,因此就增加了Scrollbar.
我应该在哪里下手?哪一个Editpart呢?
  回复  引用    

#35楼 [楼主] 2007-01-23 22:12 八进制      
diagram使用的figure要自己实现,而不能直接用gef提供的比如FreeformLayer。这个figure要能监听到editor改变大小的事件,改变自己的大小。没有实际实现过,其实freeformlayer主要的问题就在于不能自动缩小,也许可以覆盖它的一些方法实现。
  回复  引用  查看    

#36楼  2007-01-29 18:49 xalix [未注册用户]
八进制,谢谢你的答复,

我还有一个问题不是很清楚,
我现在创建了一个FreeformLayer的DiagramFigure,并使用ToolbarLayout来管理(横的),
在这Diagram里面加入几个ColumnFigure,也是使用ToolbarLayout来管理(直的),有点像本文例子。
然后在每个Column里面加入几个NodeFigure,是用ToolbarLayout来管理(横的),
在这NodeFigure里面有一个ValueFigure,这ValueFigure需要连接到其他的ValueFigure。
请问,我除了在ValueFigureEditPart里面安装GraphicalNodeEditPolicy为EditPolicy.GRAPHICAL_NODE_ROLE外,我还要安装其他什么Policy来完成联接呢?
比如在NodeEditPart里,或ColumnEditPart 及 DiagramEditPart里安装一些Policy吗?
  回复  引用    

#37楼 [楼主] 2007-01-31 22:07 八进制      
应该不需要的。
  回复  引用  查看    

#38楼  2007-01-31 23:23 xalix [未注册用户]
谢谢八进制的回答,

之前无法连接是因为在ColumnEditPart的createFigure()里面直接加入NodeEditPart,而不是用总EditPartFactory,现在问题解决了。

谢谢。
  回复  引用    

#39楼  2007-08-28 11:00 lmh [未注册用户]
在此例中,如何将其中一行的所有单元格合并呢,?
  回复  引用    

#40楼  2007-08-28 11:01 lmh [未注册用户]
急切想知道,还请尽快回复哦。
  回复  引用    

#41楼  2007-09-17 12:52 我行 [未注册用户]
哪位老兄调通过schemaeditor,请赐教“public class DummyEdgeCreator extends GraphVisitor”

“import org.eclipse.draw2d.internal.graph.GraphVisitor;”
在我的开发环境中org.eclipse.draw2d.internal包里面只有一个 MultiValueMap.class???

  回复  引用    

#42楼  2008-01-02 15:20 yangly [未注册用户]
你好,八进制:
请问如何给一个Object对象添加Property Page?
对象实现了IAdapter接口,直接返回null,
但是Project/Properties菜单不能Enabled,而且我实现的view中也不出现Properties菜单项.

我刚刚接触eclipse插件开发,希望您能给一个例子,谢谢!
  回复  引用    

#43楼 [楼主] 2008-01-02 17:27 八进制      
实现IAdapter要在adapt()方法里返回PropertyPage才可以。
  回复  引用  查看    

八进制,你好:
看了你的文章很受启发,但是现在碰到一个问题:在增加Cell时,每次增加一个cell,则系统把cell增加到columnFigure的getChildren()中的第0个元素。而没有作为childrenFigure的子元素添加,请问该怎么处理?
  回复  引用    

#45楼 [楼主] 2008-03-30 17:01 八进制      
增加cell的command应该是你自己写的吧,把里面的column.getCells().add(cell)改为column.getCells().add(index, cell)就可以了。
  回复  引用  查看    

#46楼  2008-04-10 10:29 liuyong [未注册用户]
@我行
--引用--------------------------------------------------
我行: 哪位老兄调通过schemaeditor,请赐教“public class DummyEdgeCreator extends GraphVisitor”

“import org.eclipse.draw2d.internal.graph.GraphVisitor;”
在我的开发环境中org.eclipse.draw2d.internal包里面只有一个 MultiValueMap.class???

--------------------------------------------------------

  回复  引用    

#47楼 [楼主] 2008-04-14 18:00 八进制      
应该是包名变了,现在是org.eclipse.draw2d.graph.GraphVisitor
  回复  引用  查看    

#48楼  2008-06-20 20:38 wenzhever [未注册用户]
GraphVisitor,为什么提示找不到这个类呢?去那里找这个jar呢?多谢~~~多谢~~~
  回复  引用    

#49楼 [楼主] 2008-06-21 12:01 八进制      
org.eclipse.draw2d.graph.GraphVisitor
  回复  引用  查看    

#50楼  2008-06-22 19:10 wenzhever [未注册用户]
谢谢八进制~~~
另外,我还想请教一下关于布局的问题,我现在要做的是类似于XYLayout那种的,用户拖到哪里就是哪里。但是一个figure中是可以包括若干类型的子figure的。那么子figure中的布局应该如何处理呢?另外,我还想做一个格式化功能的按钮,点击就可以自动布局当前的界面。类似eclipse中的shift+ctrl+F的功能。这个您觉得应该怎么做好呢?
  回复  引用    

#51楼 [楼主] 2008-06-22 22:47 八进制      
子figure不需要指定布局管理器。
自动布局见这篇:http://www.cnblogs.com/bjzhanghao/archive/2006/07/02/440896.html
  回复  引用  查看    

#52楼  2008-06-22 22:56 wenzhever [未注册用户]
多谢,看了您那片blog了。关于自动布局的。。。

还有一个问题,就是我的程序运行,偶发性的回抛出这样的错来:
log中内容为:

!ENTRY org.eclipse.ui.workbench 4 0 2008-06-22 22:51:25.796
!MESSAGE WARNING: Prevented recursive attempt to activate part its.edit.workprojtree.workprojtreeview while still in the middle of activating part its.prepare.sysframe.viewer.FunctionWorkProjEditor
!STACK 0
java.lang.RuntimeException: WARNING: Prevented recursive attempt to activate part its.edit.workprojtree.workprojtreeview while still in the middle of activating part its.prepare.sysframe.viewer.FunctionWorkProjEditor

。。。
就是说
Prevented recursive attempt to activate part ** while still in the middle of activating part ***

这种错误是为什么呢?我在网上也没有找大解决方法。不是每次都能重现。偶尔会在log中看到。。偶尔还会弹出个错误提示框,提示我看log。。
  回复  引用    

#53楼 [楼主] 2008-06-24 17:42 八进制      
这个问题我也遇到,暂时还没找到原因。
  回复  引用  查看    

#54楼  2008-07-02 17:49 羽毛1 [未注册用户]
八进制在前面您解答kmxht的问题时,提到的一句话:

增加cell的command应该是你自己写的吧,把里面的column.getCells().add(cell)改为column.getCells().add(index, cell)就可以了。

这个该怎么理解?我现在碰到和kmxht同学一样的问题,如果解决新增cell是放入childrenfigure而不是namefigure的呢?


  回复  引用    

#55楼 [楼主] 2008-07-02 19:13 八进制      
editpart的getContentPane()决定了子图形放在哪个区域,你的情况让childrenFigure作为contentPane就可以了。
  回复  引用  查看    

#56楼  2008-07-02 22:20 羽毛1 [未注册用户]
谢谢八进制解答.
另外还想请教一下,合并相邻节点该如何实现?还望提供点思路.
  回复  引用    

#57楼  2008-07-03 15:58 羽毛1 [未注册用户]
现在在实现表格图形编辑器又遇到了一个新问题,非常奇怪,我百思不得其解.模型包含关系是diagram-->column-->cell-->node.方法都是按照八大大的文章来实现,在diagram中添加,删除column一切正常;在column中添加cell也正常,但删除cell出现异常,点击delete键没有反应,随后把整个editor窗口最小化然后再最大化,相应的cell被删除,而且之后所有的操作都不能立刻响应到图形(包括选中),都需要先遮挡editor区域(可以最小化也可以切换到另外一个窗口)在把editor窗口放到最前,然后该操作生效.单步调的时候发现第一次点击并没有进程序,只有在遮挡的一瞬间才进入程序.这个问题困惑了我很久,刚开始以为是图形上下边越界导致异常,但修改图形尺寸后问题依然,而后我开始怀疑是否自己所写包含关系有问题,于是重新写了个很简单的2层父子包含关系一切正常....还希望能得到八大大的帮助.如果我描述的难于理解,我可以把代码发给你,谢谢.

  回复  引用    

#58楼 [楼主] 2008-07-11 23:00 八进制      
@羽毛1
一般来说在模型处,删除一个节点(保留另一个节点以及必要的信息),然后刷新界面就可以了。
  回复  引用  查看    

#59楼 [楼主] 2008-07-11 23:02 八进制      
@羽毛1
看起来是删除cell后在界面上没刷新,这个应该是cell的parent也就是column的editpart负责的,你检查一下它的editpolicy和相关代码。
  回复  引用  查看    

#60楼  2008-08-05 16:37 wukejia [未注册用户]
我现在要做一个图形编辑器,这个编辑器需要横向分成三个区域,每个区域只能向其中拖拽特定的模型,请问该用什么布局比较好啊,想了很久也没搞出来,请大牛帮忙啊,多谢。。。。。
  回复  引用    

#61楼 [楼主] 2008-08-06 19:38 八进制      
画布用toolbarlayout,每个区域里用xylayout,应该能满足。
  回复  引用  查看    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *