graphic context就象Control最顶层的画板,它可以使你向GUI components加入客制化的图形,图片,及不同字体的文本。同样也提供事件处理
graphic context是在GC类中的,GC对象是附着于现存的Controls。
要创建一个graphically oriented的应用程序,首先要创建graphic context,并将其与一个component相关联,这两步都可通过GC的constructor来实现。共有2个构造函数,见下:
1. GC(Drawable)--Creates a GC and configures it for the Drawable object
2. GC(Drawable, int)--Creates and configures a GC and sets the text-display style,第二个参数可以是RIGHT_TO_LEFT或LEFT_TO_RIGHT(默认值);
第一个参数需要实现Drawable接口的对象, 此接口包含了与graphic context.内部相联系的方法。SWT提供了三个实现Drawable接口的类:Image, Device, 和 Control.
Control子类虽然都能包含图形,但只有一个类是特别适合GC对象的:Canvas。它不仅提供了一个Composite的containment property,还可以用一系列的风格来定义图形在此区域内如何显示
示例:
package com.swtjface.Ch7;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
public class DrawExample
{
public static void main (String [] args)
{
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Drawing Example");
Canvas canvas = new Canvas(shell, SWT.NONE);
canvas.setSize(150, 150);
canvas.setLocation(20, 20);//在shell中创建canvas
shell.open ();
shell.setSize(200,220);
GC gc = new GC(canvas);//在canvas中创建graphic context
gc.drawRectangle(10, 10, 40, 45);
gc.drawOval(65, 10, 30, 35);
gc.drawLine(130, 10, 90, 80);
gc.drawPolygon(new int[] {20, 70, 45, 90, 70, 70});
gc.drawPolyline(new int[] {10,120,70,100,100,130,130,75});
gc.dispose();//释放Color对象
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
有两点需要注意:1.在调用shell.open()之前构建Canvas对象,然后在调用shell.open()之后创建和使用GC对象
2.在使用完之后一定要立即释放GC object
如上例所示GC提供了一系列在Drawable对象上画图形的方法,如下:
但是上例中有个问题:当shell被变灰过或者最小化过之后,图形就会被擦去。所以我们需要解决的事,无论window怎么变化,图形都保持可见。因此SWT在一个Drawable对象被刷新后让你自行控制。这个更新的过程就被称为painting。
Painting and PaintEvents
当一个GC方法在一个Drawabel对象上画出一个图案,它仅执行这个painting过程一次。如果用户改变对象尺寸或是用另一个窗口去覆盖它,则图形会被消除。因此,应用程序能否在外界事件影响下维持其外观这一点相当重要。
这些外部事件被称为PaintEvents,接收它们的程序接口是PaintListener。一个Control在任何时候当其外观被应用程序或是外界活动改变都会触发一个PaintEvent。这些类对于事件和监听器的使用方式都和我们在第四章内提到的类似。由于PaintListener只有一个事件处理方法,所以不需要使用adapter类
Canvas canvas = new Canvas(shell, SWT.NONE);
canvas.setSize(150, 150);
canvas.setLocation(20, 20);
canvas.addPaintListener(new PaintListener()
{
public void paintControl(PaintEvent pe)
{
GC gc = pe.gc;//每一个PaintEvent对象都包含有其自己的GC
gc.drawPolyline(new int[] {10,120,70,100,100,130,130,75});
}
});
shell.open();
每一个PaintEvent对象都包含有其自己的GC,主要有2个原因:1.因为这个GC instance是由事件产生的,所以PaintEvent会负责释放他。2.应用程序可以在shell open之前创建GC,这样可以使图形在一个独立的类中被创建。
SWT在PaintListener接口内优化painting过程,SWT的开发者强烈建议Control的painting仅对PaintEvent作出反应。如果一个应用程序因为其他原因必须更新其图形,则他们推荐使用control的redraw()方法,这会在队列中加入一个paint请求。之后,你可以调用update()方法来处理所有的绑定于该对象的paint请求。
需要牢记的是,虽然对于Control对象推荐在一个PaintListener内painting,但是由于Device和Image对象并不能在该接口内使用。如果你需要在一个image或device内生成图形,你必须单独地生成一个GC对象并在使用结束后将其销毁。
posted @
2006-04-14 11:26 JOO 阅读(540) |
评论 (0) |
编辑 收藏
要客制化layout,需要继承抽象类Layout,需要写2个方法——computeSize() 和layout().
computeSize()
protected Point computeSize(Composite composite,
int wHint, int hHint,
boolean flushCache)
{
Point maxDimensions =
calculateMaxDimensions(composite.getChildren());
int stepsPerHemisphere =
stepsPerHemisphere(composite.getChildren().length);
int maxWidth = maxDimensions.x;
int maxHeight = maxDimensions.y;
int dimensionMultiplier = (stepsPerHemisphere + 1);
int controlWidth = maxWidth * dimensionMultiplier;
int controlHeight = maxHeight * dimensionMultiplier;
int diameter = Math.max(controlWidth, controlHeight);
Point preferredSize = new Point(diameter,
diameter);
... // code to handle case when our calculations
// are too large
return preferredSize;
}
参数:
1.composite--The object we’re going to populate. At the time this method is called, it has children, but neither the composite nor the children have been sized or positioned on the screen.
2.wHint and hHint--layout所需的最大长宽。若带有参数SWT.DEFAULT,表示此layout可以随意使用use whatever sizes it decides it needs.
3.flushCache--作为flag,to tell the layout whether it’s safe to use any cached values that it may be maintaining.
computeSize()的目的主要在于计算我们要layout的composite有多大
layout()
……
posted @
2006-04-12 17:19 JOO 阅读(343) |
评论 (0) |
编辑 收藏
与之前所述的layout不同,form layout不是基于行和列的,它是基于与其他control之间的相对位置的。
FormLayout十分简单,你只要:1.设定页边距(高,宽)属性。 2.设定spacing属性,即所有control间的距离(in pixels)
同样可以使用FormData来配置单个的control。
FormData
如果一个control没有一个FormData实例来描述它的话,就会默认放在composite的右上角
width和height属性指定了control的尺寸,in pixels.
top, bottom, right, 和left属性,每一个都有一个FormAttachment实例,这些attachments描述了control与其他control之间的关系。
FormAttachment
有2个使用途径:
1.通过使用percentage of the parent composite.
2.通过设定一个control和另一个control之间的相对位置
《图》
package com.swtjface.Ch6;
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
public class Ch6FormLayoutComposite extends Composite {
public Ch6FormLayoutComposite(Composite parent) {
super(parent, SWT.NONE);
FormLayout layout = new FormLayout();
setLayout(layout);
Text t = new Text(this, SWT.MULTI);
FormData data = new FormData();
data.top = new FormAttachment(0, 0);
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(100);
data.bottom = new FormAttachment(75);//确定text的位置,因为左上角是坐标原点,所以right的百分数为100。
t.setLayoutData(data);
Button ok = new Button(this, SWT.NONE);
ok.setText("Ok");
Button cancel = new Button(this, SWT.NONE);
cancel.setText("Cancel");
data = new FormData();
data.top = new FormAttachment(t);
data.right = new FormAttachment(cancel);//ok按钮在text下面,cancel左边
ok.setLayoutData(data);
data = new FormData();
data.top = new FormAttachment(t);
data.right = new FormAttachment(100);//cancel按钮在text下面,在最右边
cancel.setLayoutData(data);
}
}
posted @
2006-04-12 12:22 JOO 阅读(377) |
评论 (0) |
编辑 收藏