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 阅读(378) |
评论 (0) |
编辑 收藏
最常用的一种layout.以row layout为基础。
package com.swtjface.Ch6;
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
public class Ch6GridLayoutComposite extends Composite {
public Ch6GridLayoutComposite(Composite parent) {
super(parent, SWT.NONE);
GridLayout layout = new GridLayout(4,false);//每一行有4个control,后一个参数是a
boolean to indicate whether the columns should take up an even amount of
space. By passing false, you tell the layout to only use the minimum amount of
space needed for each column.
setLayout(layout);
for (int i = 0; i < 16; ++i) {
Button button = new Button(this, SWT.NONE);
button.setText("Cell " + i);
}
}
}
Using GridData styles
十分类似于RowData对象。可通过其构造函数来设定STYLE,这些STYLE可分为3类:FILL, HORIZONTAL_ALIGN, and VERTICAL_ALIGN.
1.FILL:此cell是否fill所有的availabe的空间。可用的值还包括FILL_HORIZONTAL(水平扩张),FILL_VERTICAL(垂直扩张),FILL_BOTH。
2.ALIGN,用来指定control在cell中的什么位置。值包括BEGINNING, END, CENTER和FILL。
具体参见下表
Using GridData size attributes
与RowData不同,GridData还有很多的public属性。其中有些是布尔值类型的,一般会根据所设置的不同styles而自动管理,所以无需对其直接操作。还有一些是integer值,用来确定单个cells的大小。具体件下表:
posted @
2006-04-11 16:16 JOO 阅读(340) |
评论 (0) |
编辑 收藏
可以多行/列显示。
package com.swtjface.Ch6;
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
public class Ch6RowLayoutComposite extends Composite {
public Ch6RowLayoutComposite(Composite parent) {
super(parent, SWT.NONE);
RowLayout layout = new RowLayout(SWT.HORIZONTAL);
setLayout(layout);
for (int i = 0; i < 16; ++i) {
Button button = new Button(this, SWT.NONE);
button.setText("Sample Text");
}
}
}
wrap——默认为true,若设为false,所有的controls都在同一行。
pack——默认为true.使所有的child controls都大小一样。
justify——默认为false. 若为true,每一行的control都会以间隔相同的方式排列。
RowData
可以通过setLayoutData()来设定每个control的大小,如:button.setLayoutData(new RowData(200 + 5 * i, 20 + i));
posted @
2006-04-11 15:58 JOO 阅读(299) |
评论 (0) |
编辑 收藏
默认为从左到右排放的,根据每个control实际所需的大小来分配空间,此composite中多于出来的空间,再平摊到每个control上。随着composite的大小调整,control的大小也会跟着调整。
package com.swtjface.Ch6;
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
public class Ch6FillLayoutComposite extends Composite {
public Ch6FillLayoutComposite(Composite parent) {
super(parent, SWT.NONE);
FillLayout layout = new FillLayout( SWT.VERTICAL); //默认是SWT.HORIZONTAL
setLayout(layout);//为此Composite设定一个layout.如果漏了此语句,会显示不出child control。
for (int i = 0; i < 8; ++i) {
Button button = new Button(this, SWT.NONE);
button.setText("Sample Text");
}
}
}
posted @
2006-04-11 15:23 JOO 阅读(266) |
评论 (0) |
编辑 收藏
同ProgressIndicator一样,它支持工作的虚拟单位,you need only initialize the ProgressIndicator with the total amount of work you expect to do and notify it as work is completed:
ProgressIndicator indicator = new ProgressIndicator(parent);
...
indicator.beginTask(10);
...
Display.getCurrent()display.asyncExec(new Runnable() {
public void run() {
//Inform the indicator that some amount of work has been done
indicator.worked(1);
}
});
正如上例所示,使用ProgressIndicator需要2步:
1.让indicator知道总共有多少工作,通过使用beginTask().只有这个方法被调用了之后,这个control才会在屏幕上显示。
2.每当有一部分工作被完成了,就调用worked()。为了防止非ui的线程来update widgets,所以使用asyncExec()来解决这个问题。
ProgressIndicator也提供animated模式,即总工作量不知道的情况。在这种模式下,the bar continually fills and empties
until done() is called. 要使用这个模式,就要用beginAnimatedTask()代替beginTask();并且不需要worked()方法了
posted @
2006-04-10 18:07 JOO 阅读(578) |
评论 (0) |
编辑 收藏
ProgressBar,进度条,是ProgressIndicator的简化版本。大多数情况下推荐使用ProgressIndicator。如果你决定直接使用ProgressBar,需要手动改变此bar的外观。如下
//Style can be SMOOTH, HORIZONTAL, or VERTICAL
ProgressBar bar = new ProgressBar(parent, SWT.SMOOTH);
bar.setBounds(10, 10, 200, 32);
bar.setMaximum(100);
...
for(int i = 0; i < 10; i++) {
//Take care to only update the display from its
//own thread
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
//Update how much of the bar should be filled in
bar.setSelection((int)(bar.getMaximum() * (i+1) / 10));
}
});
}
setSelection()causes the widget to be updated every time.This behavior is unlike that of ProgressIndicator or ProgressMonitorDialog,which will update the display only if it has changed by an amount that will be visible to the end user.
posted @
2006-04-10 17:56 JOO 阅读(405) |
评论 (0) |
编辑 收藏
类似于scrollbars。scrollbars仅限于用在可滑动的item上,如text。
可通过setMinimum()和setMaximum()来设定它的范围。可通过setThumb()来设定滑块的值。在有些OS上,thumb的大小是常数。每按一下箭头,所移动的值称为increment.可通过setIncrement()来设定,按滑块和箭头间的空间所滑动的值为page increment,可通过PageIncrement()来设定。以上这些数据可以通过void setValues( int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement)来一次性设定,其中selection是thumb的出发点。
Slider有个属性用来设定其是水平还是垂直的,默认为水平。
package com.swtjface.Ch5;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Slider;
public class Ch5Slider extends Composite {
public Ch5Slider(Composite parent) {
super(parent, SWT.NONE);
setLayout(new FillLayout());
Slider slider = new Slider(this, SWT.HORIZONTAL);
slider.setValues(1000, 400, 1600, 200, 10, 100);
}
}
posted @
2006-04-10 17:45 JOO 阅读(257) |
评论 (0) |
编辑 收藏
类似于ToolBar的升级。他们的区别在于CoolBar上的item可以被重新配置,重新定大小。CoolBar的一般用途就是包含toolbars或按钮。
String[] coolItemTypes = {"File", "Formatting", "Search"};
CoolBar coolBar = new CoolBar(parent, SWT.NONE);
for(int i = 0; i < coolItemTypes.length; i++)
{
CoolItem item = new CoolItem(coolBar, SWT.NONE);
ToolBar tb = new ToolBar(coolBar, SWT.FLAT);
for(int j = 0; j < 3; j++)
{
ToolItem ti = new ToolItem(tb, SWT.NONE);
ti.setText(coolItemTypes[i] + " Item #" + j);
}
}
posted @
2006-04-10 17:28 JOO 阅读(333) |
评论 (0) |
编辑 收藏
是JFace的类,继承自ContributionManager,凡是继承了IAction或IContribution接口的对象都可被加至ToolBarManager.你只要花时间为ToolBarManager添加Action,Toolbar和ToolItem实例会自动产生。
你可通过调用ApplicationWindow的createToolBarManager()来为你的应用程序添加一个toolbar。与MenuManager不同的是,createToolBarManager()需要一个style参数,这个参数用来设定ToolBar所用的按钮的风格:flat或normal。
除了MenuManager所用的ContributionItems之外,还有一个新的ContributionItem,只能被ToolBarManager使用——ControlContribution。这个类可将任何能被用于toolbar的Control打包进去。
要使用ControlContribution类,必须要实现抽象方法createControl().
toolBarManager.add(new ControlContribution("Custom") {
protected Control createControl(Composite parent) {
SashForm sf = new SashForm(parent, SWT.NONE);
Button b1 = new Button(sf, SWT.PUSH);
b1.setText("Hello");
Button b2 = new Button(sf, SWT.PUSH);
b2.setText("World");
b2.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
System.out.println("Selected:" + e);
}
});
return sf;
}
});
如果你希望有任何的事件发生,必须在你的controls上实现SelectionListeners
-
Creating toolbars by hand
如果你不想ToolBarManager来创建toolbar的话,可以手动创建,需要用到ToolBar和ToolItem类.
Toolbar
是一个composite control,包含多个ToolItems.Toolbar由多个小图标按钮组成,一般是16-by-16bitmap图片。每个按钮都对应一个ToolItem。Toolbar可以是水平的也可以是垂直的,默认为水平
ToolItem
每一个ToolItem都有一个图片,如果没有,默认为红色方块。When the user selects a ToolItem from the menu, it broadcasts the event to any registered SelectionListeners.Your application should register a listener with each ToolItem and use that listener to perform whatever logic corresponds to the menu item.
posted @
2006-04-07 16:32 JOO 阅读(665) |
评论 (0) |
编辑 收藏
三种类型的Combo control:
1.Simple:默认类型,一个可编辑的text field和一个供选择的list
2.Drop-down:下拉列表,文本框可编辑
3.Read-only:文本框不可编辑的下拉列表,可用select( 0 )来将其默认选中列表中的首项。
以上三种类型可在构造函数中通过STYLE.*来设置。
posted @
2006-04-07 16:30 JOO 阅读(271) |
评论 (0) |
编辑 收藏
先要将org.eclipse.text_x.y.z和org.eclipse.jface.text_x.y.z加到classpath
两个重要的接口:IDocument和ITextViewer。JFace为其提供了默认的实现。
一个IDocument的实例持有被编辑的真实的文本信息。它的主要实现是Document类。AbstractDocument提供了部分实现,你可通过继承它来添加自己的实现。IDocument允许通过IDocumentListener接口来获取内容编辑的通知。
IDocument还提供了以下功能
Positions
可以给每一个text区域分配一个记号来作为它的Position。当被指定给某个ducument时一个Position对象有an offset and a length of text。如果document的text被更新的话,Position也会同步更新,所以他永远都是指向同一段文字。Position类本身提供了一些基本的功能,可通过继承他来完善更多有用的功能。
Partition content types
每个document由一个或多个partitions组成,通过ITypedRegion接口来表现。每一个partition可以有各自的内容类型,如plain text, rich text, or HTML。要使用它,你要创建一个IDocumentPartitioner然后assign给你的document,然后document的partitioner就会负责响应对指定位置内容类型的查询,它必须通过实现computePartitioning()来返回包含此document中所有ITypedRegions的一个数组。不需要实现你自己的document partitioner。如果没有创建,整个document就是一个区域,类型为IDocument.DEFAULT_CONTENT_TYPE。
Searching
IDocument通过search()提供了搜索的功能。不支持regular expressions or other patterns,但提供了search start location,direction, and case sensitivity and whether to match whole words only.
ITextViewer将一个标准的text widget转换成一个基于document的text widget
ITextViewer的默认实现是TextViewer,它使用StyledText来显示数据。ITextViewer支持text modifications的listener,也支持visual events(如改变viewport,即text的当前可视区域)的监听器。
虽然作为ITextViewer的默认应用,如果你想要修改显示,TextViewer允许你直接accessStyledText,但建议你使用TextPresentation,因为它可以收集该文档中带有的各个不同的StyleRanges。
ITextViewer还支持很多不同类型的插件,可用来修改widget的行为。可以被customized的功能有:
1.通过IUndoManager来支持undo
2.通过ITextDoubleClickStrategy来支持对鼠标双击的处理
3.通过IAutoIndentStrategy来支持文本的自动缩进
4.通过ITextHover来实现,当鼠标停留在document的一个section上时,显示text.
要使用上述插件,你需要分配一个适当的接口实例给text viewer,然后调用activatePlugins().
如下列出了org.eclipse.jface.text的子包及其作用
posted @
2006-04-04 15:02 JOO 阅读(416) |
评论 (0) |
编辑 收藏