八进制

少年壮志无烟抽

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  235 随笔 :: 0 文章 :: 3088 评论 :: 14 引用

就像在swt里我们使用layout来控制各个控件的摆放位置一样,在Draw2D里最好也把这个工作交给LayoutManager来做。除非是在自己实现的Layout里,一般程序里自己不要轻易使用setBounds()、setLocation()和setSize()这些方法控制图形的位置和大小,而应该在为每个图形设置了适当的LayoutManager后,通过setConstraint()和setPreferredSize()等方法告诉layoutmanager如何布局。

在需要的时候,父图形的布局管理器负责修改每个子图形的位置和大小,但计算每个子图形大小的工作可能是交给子图形自己的LayoutManager来做的,计算的方法一般是在这个LayoutManager的getPreferredSize()方法里体现。

例如当父图形使用XYLayout,子图形使用ToolbarLayout时,假设在子图形里又增加了子子图形(子图形里的子图形),add()方法会导致revalidate()的调用,这时父图形的xylayout将检查子图形是否具有constraint,如果有并且有至少一个方向为-1,则利用子图形上的ToolbarLayout计算出子图形新的尺寸,这个尺寸是和子图形里包含的子子图形的数目有关的(ToolbarLayout会把每个子图形的宽/高度加起来,加上其中间隔的空间,再考虑图形的边框,返回得到的尺寸)。

XYLayout对layout(IFigure)方法的实现:

public void layout(IFigure parent) {
    Iterator children 
= parent.getChildren().iterator();
    Point offset 
= getOrigin(parent);
    IFigure f;
    
while (children.hasNext()) {
        f 
= (IFigure)children.next();
        Rectangle bounds 
= (Rectangle)getConstraint(f);//因此必须为子图形指定constraint
        if (bounds == nullcontinue;

        
if (bounds.width == -1 || bounds.height == -1) {
            Dimension preferredSize 
= f.getPreferredSize(bounds.width, bounds.height);
            bounds 
= bounds.getCopy();
            
if (bounds.width == -1)
                bounds.width 
= preferredSize.width;
            
if (bounds.height == -1)
                bounds.height 
= preferredSize.height;
        }
        bounds 
= bounds.getTranslated(offset);
        f.setBounds(bounds);
    }
}

Draw2D里Figure类的setPreferredSize(Dimension)和setSize(Dimension)的区别是,setSize()方法不会调用revalidate()方法导致重新layout,而只是调用repaint()对所涉及到的“脏”区域进行重绘(repaint)。setPreferredSize()方法可以约等于setSize()方法+revalidate()方法,因为在Figure对getPreferredSize(int,int)的实现里,若该figure没有任何layoutmanager,则返回当前size:

public Dimension getPreferredSize(int wHint, int hHint) {
    
if (prefSize != null)
        
return prefSize;
    
if (getLayoutManager() != null) {
        Dimension d 
= getLayoutManager().getPreferredSize(this, wHint, hHint);
        
if (d != null)
            
return d;
    }
    
return getSize();
}
 

只要看一下ToolbarLayout.java就会知道,ToolbarLayout对constraint是不感兴趣的,调用它的getConstraint()永远返回null值,所以我们不必对放在使用ToolbarLayout的图形的子图形设置constraint。因此,假如我们的问题是,有图形A包含B,B包含C,要实现B(使用ToolbarLayout)尺寸随C数目多少而自动改变该如何做呢?这要看A使用何种LayoutManager,如果是ToolbarLayout则不用做特殊的设置,如果是XYLayout则要用A.getLayoutManager().setConstraint(B,new Rectangle(x,y,-1,-1))这样的语句为A设置constraint,对图形C则用setPreferredSize()指定实际大小。

一个Layout的例子,点此下载,截图如下。


posted on 2006-09-05 21:36 八进制 阅读(3855) 评论(29)  编辑 收藏 网摘 所属分类: EclipseGEF

评论

#1楼  2006-09-28 12:09 傲其 [未注册用户]
八进制你好!
我在前面看了你的右键菜单的实现方法,我想给右键菜单添加一个连接功能。跟Palette里面的connection一样。 就是点这个action的时候就调出一个连接工具,跟点palette里面的连接时出来的工具一样。怎么实现?

  回复  引用    

编辑器中,通过实现PaletteRoot工具,在工具箱中上面添加模型,可以将自己定义的模型拖入到编辑器中

那如何将视图中,视图中有TreeViewer的树形节点(每个节点都有相应的模型对应)拖入到编辑器中呢?
  回复  引用    

#3楼  2007-07-11 11:33 hehui0912 [未注册用户]
我自己写的一个layout  manager ,大家参考一下。



/*******************************************************************************
* Copyright (c) 2000, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.example.layout;

import java.util.Iterator;

import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;

/**
* A layout for {@link org.eclipse.draw2d.FreeformFigure FreeformFigures}.
*/
public class FreeformLayout2
extends FreeformLayout
{
int colum;

int width;


public FreeformLayout2(int colum, int width) {

this.colum = colum;
this.width = width;

}



public void layout(IFigure parent) {



// parent.set


//System.out.println(parent.getClass().toString());




//parent.getBounds().x=10;
//parent.getBounds().y=20;
parent.invalidate();

int x = parent.getBounds().x;
int y = parent.getBounds().y;


int ph = parent.getBounds().height;
int pw = parent.getBounds().width;

int h = parent.getBounds().height / this.width;
int w = parent.getBounds().width / this.colum;
// System.out.println(ph+" "+pw);
Iterator children = parent.getChildren().iterator();
//System.out.println(x+" "+y);


IFigure f;

int cx =x, cy =y;
int count=0;
while (children.hasNext()) {
count++;

//System.out.println(pw);
f = (IFigure) children.next();

f.setLocation(new Point(cx, cy));
// System.out.println("x= "+cx+" y= "+cy );


f.setSize(w, w);
cx +=w;
if (count>=colum) {
cx =x;
cy +=w;
count=0;
}


}

}




}

  回复  引用    

#4楼  2007-07-26 16:41 jiezi [未注册用户]
constraint,如果有并且有至少一个方向为-1
请问-1是指什么方向?还有哪些方向用数字表示?
  回复  引用    

#5楼 [楼主] 2007-07-27 11:13 八进制      
x或y方向,值是-1,并不是说数字代表方向。
  回复  引用  查看    

#6楼  2007-07-27 13:08 jiezi [未注册用户]
x还是向左负、向右正,y还是向下负、向上正么?
bounds.width == -1
这个是指从bound的(x,y)向左距离为1么?
  回复  引用    

#7楼 [楼主] 2007-07-27 17:21 八进制      
左上角为(0,0),向右向下为正。bounds.width表示宽度,bounds.x表示横坐标。
  回复  引用  查看    

#8楼  2007-08-20 18:44 jiezi [未注册用户]
八进制大大,对于ToolbarLayout内的图形,可以用setPreferredSize(width,height)来设置长宽?
为什么我使用ToolbarLayout布局内(竖直方向)的图形,width方向自动跟随editor长度,而height方向长度与setPreferredSize()里height从视觉上看起来差很多
  回复  引用    

#9楼 [楼主] 2007-08-21 21:37 八进制      
ToolbarLayout里的图形尺寸与子图形的preferred size有关,但如果设置了stretchMinorAxis则子图形会被拉大。
  回复  引用  查看    

#10楼  2007-08-22 17:24 aphrodite [未注册用户]
八进制,请问在水平布局时,我想让每个子图形的顶部与包含他的父图标上边框隔着一段距离,这个应该在哪里修改呢?
  回复  引用    

#11楼 [楼主] 2007-08-22 20:06 八进制      
给父图形设置一个MarginBorder
  回复  引用  查看    

#12楼  2007-08-23 17:28 aphrodite [未注册用户]
我又发现一个问题 往父图标中添加子图标时,调用addChildVisual方法,这时加入得子图标的坐标用getbound方法取出来为(0,0),能解释一下是怎么回事吗?我想得到子图标的坐标,应该怎么得到呢?
  回复  引用    

#13楼 [楼主] 2007-08-23 23:22 八进制      
为什么用addChildVisual()而不是add()?
  回复  引用  查看    

#14楼  2007-08-24 09:57 aphrodite [未注册用户]
addChild方法会调用addChildVisual()阿,然后addChildVisual()使用getContentPane().add(child, index); 这样加入子图标之后,子图标的位置能取出来吗? 我自己写了一个addChildVisual()方法,先super一下,然后取出来的子图标位置就为(0,0)了,不知为何??
  回复  引用    

#15楼  2007-08-27 10:21 aphrodite [未注册用户]
请问八进制 加入子图标后 在父容器中用什么方法 什么时候能得到子图标的坐标?我调试了好几天没有结果,恳请指教
  回复  引用    

#16楼 [楼主] 2007-08-27 18:16 八进制      
先得到子图形child,然后child.getBounds()
  回复  引用  查看    

#17楼  2007-08-29 21:09 jiezi [未注册用户]
大大有没有比较大,比较花哨的那种迁移线的箭头figure实现的例子,有的话能给个么,链接也行
  回复  引用    

#18楼  2007-09-04 20:29 aphrodite [未注册用户]
八进制阁下 请问我想实现:选中图片后,在容器里点击一个子图片到另一个子图片的连线,就可以在这两个图片之间插入选中图片 。这个是不是要自己写一个layout?应该怎样实现呢?我得容器用的是ConstrainedToolbarLayout。
  回复  引用    

#19楼  2007-09-10 22:04 aphrodite [未注册用户]
八进制大人 请问上述的加入图片操作是否应该修改模型层 再刷新视图实现?摸不到头脑.. 谢谢
  回复  引用    

#20楼 [楼主] 2007-09-11 14:42 八进制      
绝大多数操作都应该先修改模型,视图的更新由注册在模型上的监听器(例如editpart)完成。你说的这个需求我没实现过,感觉应该用自定义request完成,你可以参考这篇:http://www.cnblogs.com/bjzhanghao/archive/2007/08/28/792446.html
  回复  引用  查看    

#21楼  2007-09-17 22:20 aphrodite [未注册用户]
八进制大大 非常感谢您对我的帮助 给了我探索的方向
我仔细看了你说得request的文章 然后看了下refreshchildren方法 发现他是不断的用getmodelchildren与getchildren做对比 来实现子图标添加删除的.
那么 我要实现的是 点击选项板中图标 然后在toolbarlayout的容器里 选中一个子图标 就会在子图标下方(上方)自动加入选项板中图标 是否 我可以先修改容器中受影响的子图标模型的位置 然后refreshchildren来实现?
应该怎样实现位置的改变呢..? 我这个思路可以吗

  回复  引用    

#22楼  2007-09-18 10:31 aphrodite [未注册用户]
还有一个问题 在以toolbarlayout布局的容器里 加入新图片时 为什么不能点击到容器中已有的图片上?只能选择空白出点击? 是否因为容器中子图片没有提供监听功能?我想让他能够被点击怎么办?
  回复  引用    

#23楼 [楼主] 2007-09-18 13:49 八进制      
1. 位置改变似乎toolbarlayout已经能实现了,我觉得你要做的就是在model里增加一个child然后refreshChildren(),不确定我是否理解了你的需求。
2. 如果用户在图元上点击他怎么知道新创建的图元出现在上面还是下面,所以在空白处点击是更为正确的方式。

  回复  引用  查看    

#24楼  2007-09-18 18:47 aphrodite [未注册用户]
那点击空白处怎么知道新图片的上方跟下方各有那些child?能取出这个位置信息来吗? 这块监听应该在哪里实现呢 ??
还有 toolbarlayout布局的容器 点击空白处就直接将子图片排到最后了阿 我要修改他的监听 是不是还要改它布局的那套逻辑?...谢谢 我再调试一阵:)
  回复  引用    

#25楼 [楼主] 2007-09-19 13:57 八进制      
FlowLayoutEditPolicy会根据点击的空白位置告诉你新创建的child在model里应该加在哪个child前面。你可以参考这篇http://bjzhanghao.cnblogs.com/archive/2005/03/24/124497.html
  回复  引用  查看    

#26楼  2007-09-19 21:36 aphrodite [未注册用户]
我是在gmf下调试的 发现在加入子图片时,点击容器后有creationtool调用handleButtonUp方法,然后里面调用performCreation方法,在他其中getCurrentCommand直接就能得到创建的命令.没有涉及request,EditPolicy之间的联系?就直接得到command了? 然后就引起视图刷新了..
那我想知道 我要修改模型 在model里增加一个child ,发出command的切入点在哪里??
sorry 有些晕..
  回复  引用    

#27楼  2007-10-08 10:44 aphrodite [未注册用户]
八进制大人 前阵杂事太多 没能继续研究这一块 现在开始加紧了
还是恳请您指导下 我得上述需求 要修改模型,在model里增加child,应该是在那个地方修改?
是Targeting Tool里get Target EditPart()可以设置图片的监听吗?
我跟踪代码 是UnspecifiedTypeCreationTool监听了点击事件 ,跟您写的那篇自定义request流程上很不相同 能给我讲一下具体要怎么做吗??
谢谢!!
  回复  引用    

#28楼  2008-05-15 10:57 baozi [未注册用户]
八进制, 急切盼望指点 ,我快郁闷坏了。。
我现在做了一个FlowCompartmentEditPart,继承ResizableCompartmentEditPart,上面加了ToolbarLayout的水平布局,想在flow容器中加入子活动时,子活动到容器的顶部,能空出一块间距,以便画连线。
现在我尝试在FlowCompartmentEditPart里createFigure时用getContentPane().setBorder(new MarginBorder(15)),但是加了border之后,发现边距增大了 可是用polilyconnection画线时,这块边距画不上线为什么?是因为里面scorllpane的边距是没法画线的?

那应该用什么办法在加入子活动时,自动增大顶部的边距? 是否必须要改布局算法才行? 我得困惑是,如果单纯修改了toolbarlayout里面layout方法中加入子元素的纵坐标,边距变大了,但是外层的容器没有随之变大,应该用什么方法来通知容器做出相应改变?
  回复  引用    

#29楼 [楼主] 2008-05-20 14:03 八进制      
设置toolbarlayout的spacing行不行?另一个可能的办法是覆盖toolbarlayout的calculatePreferredSize()方法,这个方法应该返回容器的尺寸,你让它变大一些试试。
要想让容器随子元素变大,就得用toolbarlayout这类布局。
  回复  引用  查看    





标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2006-09-05 21:41 编辑过
Google站内搜索

China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!
开发者征途系统新作:《设计模式——基于C#的工程化实现及扩展》

相关文章:

相关链接: