`

draw2d详述(IFigure)

 
阅读更多

 

1.IFigure

IFigure接口是所有Figure的基础接口,里面有很多方法,这里只列出部分自己觉得有用的方法:

 

(1)add(IFigure figure, Object constraint, int index):添加一个子,并且指定其约束和位置:

 

 

public void add(IFigure figure, Object constraint, int index) {
		if (children == Collections.EMPTY_LIST)
			children = new ArrayList(2);
		if (index < -1 || index > children.size())
			throw new IndexOutOfBoundsException("Index does not exist"); //$NON-NLS-1$

		// Check for Cycle in hierarchy
		for (IFigure f = this; f != null; f = f.getParent())
			if (figure == f)
				throw new IllegalArgumentException(
						"Figure being added introduces cycle"); //$NON-NLS-1$

		// Detach the child from previous parent
		if (figure.getParent() != null)
			figure.getParent().remove(figure);

		if (index == -1)
			children.add(figure);
		else
			children.add(index, figure);
		figure.setParent(this);

		if (layoutManager != null)
			layoutManager.setConstraint(figure, constraint);

		revalidate();

		if (getFlag(FLAG_REALIZED))
			figure.addNotify();
		figure.repaint();
	}

 

(2)getPreferredSize:获取首选大小,这个大小多半会在layout里面用到。

 

(3)isCoordinateSystem:是否使用相对坐标

 

(4)isFocusTraversable:是否可以得到焦点

 

(5)isMirrored:是否有镜像效果

 

(6)isOpaque:是否透明

 

(7)paint(Graphics graphics):组件最重要的方法,画。

 

 

public void paint(Graphics graphics) {
		if (getLocalBackgroundColor() != null)
			graphics.setBackgroundColor(getLocalBackgroundColor());
		if (getLocalForegroundColor() != null)
			graphics.setForegroundColor(getLocalForegroundColor());
		if (font != null)
			graphics.setFont(font);

		graphics.pushState();
		try {
			paintFigure(graphics);
			graphics.restoreState();
			paintClientArea(graphics);
			paintBorder(graphics);
		} finally {
			graphics.popState();
		}
	}

 

 可以看出它把画这个行为分解了:

 

 

protected void paintFigure(Graphics graphics) {
		if (isOpaque())
			graphics.fillRectangle(getBounds());
		if (getBorder() instanceof AbstractBackground)
			((AbstractBackground) getBorder()).paintBackground(this, graphics,
					NO_INSETS);
	}

 

看它的透明是怎样实现的:把父画一遍就OK,多简单。

 

 

protected void paintClientArea(Graphics graphics) {
		if (children.isEmpty())
			return;

		boolean optimizeClip = getBorder() == null || getBorder().isOpaque();

		if (useLocalCoordinates()) {
			graphics.translate(getBounds().x + getInsets().left, getBounds().y
					+ getInsets().top);
			if (!optimizeClip)
				graphics.clipRect(getClientArea(PRIVATE_RECT));
			graphics.pushState();
			paintChildren(graphics);
			graphics.popState();
			graphics.restoreState();
		} else {
			if (optimizeClip)
				paintChildren(graphics);
			else {
				graphics.clipRect(getClientArea(PRIVATE_RECT));
				graphics.pushState();
				paintChildren(graphics);
				graphics.popState();
				graphics.restoreState();
			}
		}
	}

 

 

protected void paintChildren(Graphics graphics) {
		for (int i = 0; i < children.size(); i++) {
			IFigure child = (IFigure) children.get(i);
			if (child.isVisible()) {
				// determine clipping areas for child
				Rectangle[] clipping = null;
				if (clippingStrategy != null) {
					clipping = clippingStrategy.getClip(child);
				} else {
					// default clipping behaviour is to clip at bounds
					clipping = new Rectangle[] { child.getBounds() };
				}
				// child may now paint inside the clipping areas
				for (int j = 0; j < clipping.length; j++) {
					if (clipping[j].intersects(graphics
							.getClip(Rectangle.SINGLETON))) {
						graphics.clipRect(clipping[j]);
						child.paint(graphics);
						graphics.restoreState();
					}
				}
			}
		}
	}
 

 

protected void paintBorder(Graphics graphics) {
		if (getBorder() != null)
			getBorder().paint(this, graphics, NO_INSETS);
	}
 

其实画的过程还是挺清晰的,就是从底往上一层层的画。只是,画并不难,难的是算,如何让子进行排列这是个棘手的事。

 

 

 

2.LayoutManager在Figure里面的应用

 

在Figure里面,所有涉及到获取大小位置信息的,都要从LayoutManager里面过一遍,经过它计算后才能够被使用者获取到,有时候吧,我们总会很2的感觉自己获取的值怎么是什么样的,其实就是对里面的细节没有像清楚。

 

 

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

 

 

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();
	}
 

 

public void setConstraint(IFigure child, Object constraint) {
		if (child.getParent() != this)
			throw new IllegalArgumentException("Figure must be a child"); //$NON-NLS-1$

		if (layoutManager != null)
			layoutManager.setConstraint(child, constraint);
		revalidate();
	}
 

 

final class LayoutNotifier implements LayoutManager {

		LayoutManager realLayout;
		List listeners = new ArrayList(1);

		LayoutNotifier(LayoutManager layout, LayoutListener listener) {
			realLayout = layout;
			listeners.add(listener);
		}

		public Object getConstraint(IFigure child) {
			if (realLayout != null)
				return realLayout.getConstraint(child);
			return null;
		}

		public Dimension getMinimumSize(IFigure container, int wHint, int hHint) {
			if (realLayout != null)
				return realLayout.getMinimumSize(container, wHint, hHint);
			return null;
		}

		public Dimension getPreferredSize(IFigure container, int wHint,
				int hHint) {
			if (realLayout != null)
				return realLayout.getPreferredSize(container, wHint, hHint);
			return null;
		}

		public void invalidate() {
			for (int i = 0; i < listeners.size(); i++)
				((LayoutListener) listeners.get(i)).invalidate(Figure.this);

			if (realLayout != null)
				realLayout.invalidate();
		}

		public void layout(IFigure container) {
			boolean consumed = false;
			for (int i = 0; i < listeners.size(); i++)
				consumed |= ((LayoutListener) listeners.get(i))
						.layout(container);

			if (realLayout != null && !consumed)
				realLayout.layout(container);
			for (int i = 0; i < listeners.size(); i++)
				((LayoutListener) listeners.get(i)).postLayout(container);
		}

		public void remove(IFigure child) {
			for (int i = 0; i < listeners.size(); i++)
				((LayoutListener) listeners.get(i)).remove(child);
			if (realLayout != null)
				realLayout.remove(child);
		}

		public void setConstraint(IFigure child, Object constraint) {
			for (int i = 0; i < listeners.size(); i++)
				((LayoutListener) listeners.get(i)).setConstraint(child,
						constraint);
			if (realLayout != null)
				realLayout.setConstraint(child, constraint);
		}
	}

 这里还有个事件监听,实时对container重新计算。上述是LayoutManager在IFigure里面的使用。

 

 

 

3.LayoutManager:

LayoutManager的几个接口都是在Figure类里面用到,其中比较关键的void layout(IFigure container);是在它的LayoutNotifier里面调用的,当监听到需要改变布局的时候,就会调用此方法。

 

(1)XYLayout:

 

 

protected Dimension calculatePreferredSize(IFigure f, int wHint, int hHint) {
		Rectangle rect = new Rectangle();
		ListIterator children = f.getChildren().listIterator();
		while (children.hasNext()) {
			IFigure child = (IFigure) children.next();
			Rectangle r = (Rectangle) constraints.get(child);
			if (r == null)
				continue;

			if (r.width == -1 || r.height == -1) {
				Dimension preferredSize = child.getPreferredSize(r.width,
						r.height);
				r = r.getCopy();
				if (r.width == -1)
					r.width = preferredSize.width;
				if (r.height == -1)
					r.height = preferredSize.height;
			}
			rect.union(r);
		}
		Dimension d = rect.getSize();
		Insets insets = f.getInsets();
		return new Dimension(d.width + insets.getWidth(), d.height
				+ insets.getHeight()).union(getBorderPreferredSize(f));
	}

 计算首选大小

 

 

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);
			if (bounds == null)
				continue;

			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);
		}
	}
 

计算布局:最终会把计算到的值,赋值给IFigure:f.setBounds(bounds);

 

 

(2)其他的以后再分析,其实就是按照某种规则算,算大小什么的,其它的都是浮云。

 

分享到:
评论

相关推荐

    draw2d_Demo_code

    在代码中,我们可能会看到`IFigure`接口的实现,它是Draw2D中所有图形对象的基类。 2. **布局管理器**:在`Draw2DLayoutExample.java`中,布局管理器如`GridLayout`或`FlowLayout`被用来组织和调整图形对象的位置。...

    draw2d精讲

    首先,Draw2D的实例通常由三部分组成:SWT组件、LightweightSystem以及Draw2D的IFigure实例集合。其中,SWT(Standard Widget Toolkit)是用于Java开发的一个跨平台GUI工具包,而LightweightSystem是连接SWT和Draw2D...

    关于Draw2D里的Layout.doc

    在Draw2D图形库中,Layout管理器是一个至关重要的组件,它负责控制图形元素的排列方式和尺寸。正如在SWT(Standard Widget Toolkit)中利用`layout`来组织控件的位置,Draw2D中的`LayoutManager`同样扮演着布局管理...

    GEF基础知识

    这是因为GEF的很多核心概念与API设计都是与Draw2D紧密相关的,尤其是它的`AbstractGraphicalEditPart`类中的`createFigure()`方法,要求返回的是Draw2D中的`IFigure`对象。因此,要深入理解和使用GEF,了解Draw2D的...

    drawjs:eclipse draw2d的端口

    []梳理draw2d的Java类继承关系1.1 [x]放置IFigure类图1.2 [x]放置EventDispatcher类图1.2.1 [] SWTEventDispatcher类图(实现)1.3 [x]替换UpdateManager类图1.3.1 [] DeferredUpdateManager类图(实现)1.4 [x]...

    Eclipse_GEF.doc

    IFigure是Draw2D提供的一个接口,用于绘制各种图形元素。 ##### 2. **EditPolicy** - **EditPolicy** 负责处理特定类型的用户请求,并将这些请求转化为对模型的操作。每个EditPart可以安装多个EditPolicy。 - 当...

    用gef写的一个tree例子(无移动,删除)

    - 实现`IFigure`和`IFigurePart`接口,以定义树节点的外观和行为。 - 使用`EditPolicy`定义节点的操作,如添加、删除等。在这个例子中,由于不包含移动和删除功能,可能只实现了基本的显示和选择操作。 - 创建一个`...

    按名称调用图形,使用滚轮缩放等:按名称而不是手柄引用图形,还包括滚轮缩放、平移、持久图形位置和大小等-matlab开发

    按名称而不是句柄引用图形,还包括滚轮缩放和平移...fHandle = iFigure('My Figure', 'zoom') 会将图形打开到它之前的位置,并使用基于滚轮的缩放和平移。 一些键盘键将允许多子图图像的同步缩放(在 x、y 或两者中)。

Global site tag (gtag.js) - Google Analytics