The Goal
Keep walking…… |
當(dāng)一個(gè)GC方法在一個(gè)Drawabel對(duì)象上畫出一個(gè)圖案,它僅執(zhí)行這個(gè)painting過(guò)程一次。如果用戶改變對(duì)象尺寸或是用另一個(gè)窗口去覆蓋它,則圖形會(huì)被消除。因此,應(yīng)用程序能否在外界事件影響下維持其外觀這一點(diǎn)相當(dāng)重要。
這些外部事件被稱為PaintEvents,接收它們的程序接口是PaintListener。一個(gè)Control在任何時(shí)候當(dāng)其外觀被應(yīng)用程序或是外界活動(dòng)改變都會(huì)觸發(fā)一個(gè)PaintEvent。這些類對(duì)于事件和監(jiān)聽器的使用方式都和我們?cè)诘谒恼聝?nèi)提到的類似。由于PaintListener只有一個(gè)事件處理方法,所以不需要使用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;//每一個(gè)PaintEvent對(duì)象都包含有其自己的GC
gc.drawPolyline(new int[] {10,120,70,100,100,130,130,75});
}
});
shell.open();
每一個(gè)PaintEvent對(duì)象都包含有其自己的GC,主要有2個(gè)原因:1.因?yàn)檫@個(gè)GC instance是由事件產(chǎn)生的,所以PaintEvent會(huì)負(fù)責(zé)釋放他。2.應(yīng)用程序可以在shell open之前創(chuàng)建GC,這樣可以使圖形在一個(gè)獨(dú)立的類中被創(chuàng)建。
SWT在PaintListener接口內(nèi)優(yōu)化painting過(guò)程,SWT的開發(fā)者強(qiáng)烈建議Control的painting僅對(duì)PaintEvent作出反應(yīng)。如果一個(gè)應(yīng)用程序因?yàn)槠渌虮仨毟缕鋱D形,則他們推薦使用control的redraw()方法,這會(huì)在隊(duì)列中加入一個(gè)paint請(qǐng)求。之后,你可以調(diào)用update()方法來(lái)處理所有的綁定于該對(duì)象的paint請(qǐng)求。
需要牢記的是,雖然對(duì)于Control對(duì)象推薦在一個(gè)PaintListener內(nèi)painting,但是由于Device和Image對(duì)象并不能在該接口內(nèi)使用。如果你需要在一個(gè)image或device內(nèi)生成圖形,你必須單獨(dú)地生成一個(gè)GC對(duì)象并在使用結(jié)束后將其銷毀。
要客制化layout,需要繼承抽象類Layout,需要寫2個(gè)方法——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;
}
參數(shù):
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所需的最大長(zhǎng)寬。若帶有參數(shù)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()的目的主要在于計(jì)算我們要layout的composite有多大
layout()
……
與之前所述的layout不同,form layout不是基于行和列的,它是基于與其他control之間的相對(duì)位置的。
FormLayout十分簡(jiǎn)單,你只要:1.設(shè)定頁(yè)邊距(高,寬)屬性。 2.設(shè)定spacing屬性,即所有control間的距離(in pixels)
同樣可以使用FormData來(lái)配置單個(gè)的control。
FormData
如果一個(gè)control沒(méi)有一個(gè)FormData實(shí)例來(lái)描述它的話,就會(huì)默認(rèn)放在composite的右上角
width和height屬性指定了control的尺寸,in pixels.
top, bottom, right, 和left屬性,每一個(gè)都有一個(gè)FormAttachment實(shí)例,這些attachments描述了control與其他control之間的關(guān)系。
FormAttachment
有2個(gè)使用途徑:
1.通過(guò)使用percentage of the parent composite.
2.通過(guò)設(shè)定一個(gè)control和另一個(gè)control之間的相對(duì)位置?
《圖》
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的位置,因?yàn)樽笊辖鞘亲鴺?biāo)原點(diǎn),所以right的百分?jǐn)?shù)為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);
}
}
最常用的一種layout.以row layout為基礎(chǔ)。
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個(gè)control,后一個(gè)參數(shù)是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對(duì)象??赏ㄟ^(guò)其構(gòu)造函數(shù)來(lái)設(shè)定STYLE,這些STYLE可分為3類:FILL, HORIZONTAL_ALIGN, and VERTICAL_ALIGN.
1.FILL:此cell是否fill所有的availabe的空間??捎玫闹颠€包括FILL_HORIZONTAL(水平擴(kuò)張),FILL_VERTICAL(垂直擴(kuò)張),FILL_BOTH。
2.ALIGN,用來(lái)指定control在cell中的什么位置。值包括BEGINNING, END, CENTER和FILL。
具體參見下表
Using GridData size attributes
與RowData不同,GridData還有很多的public屬性。其中有些是布爾值類型的,一般會(huì)根據(jù)所設(shè)置的不同styles而自動(dòng)管理,所以無(wú)需對(duì)其直接操作。還有一些是integer值,用來(lái)確定單個(gè)cells的大小。具體件下表:
默認(rèn)為從左到右排放的,根據(jù)每個(gè)control實(shí)際所需的大小來(lái)分配空間,此composite中多于出來(lái)的空間,再平攤到每個(gè)control上。隨著composite的大小調(diào)整,control的大小也會(huì)跟著調(diào)整。
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); //默認(rèn)是SWT.HORIZONTAL
setLayout(layout);//為此Composite設(shè)定一個(gè)layout.如果漏了此語(yǔ)句,會(huì)顯示不出child control。
for (int i = 0; i < 8; ++i) {
Button button = new Button(this, SWT.NONE);
button.setText("Sample Text");
}
}
}
是JFace的類,繼承自ContributionManager,凡是繼承了IAction或IContribution接口的對(duì)象都可被加至ToolBarManager.你只要花時(shí)間為ToolBarManager添加Action,Toolbar和ToolItem實(shí)例會(huì)自動(dòng)產(chǎn)生。
你可通過(guò)調(diào)用ApplicationWindow的createToolBarManager()來(lái)為你的應(yīng)用程序添加一個(gè)toolbar。與MenuManager不同的是,createToolBarManager()需要一個(gè)style參數(shù),這個(gè)參數(shù)用來(lái)設(shè)定ToolBar所用的按鈕的風(fēng)格:flat或normal。
除了MenuManager所用的ContributionItems之外,還有一個(gè)新的ContributionItem,只能被ToolBarManager使用——ControlContribution。這個(gè)類可將任何能被用于toolbar的Control打包進(jìn)去。
要使用ControlContribution類,必須要實(shí)現(xiàn)抽象方法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;
}
});
如果你希望有任何的事件發(fā)生,必須在你的controls上實(shí)現(xiàn)SelectionListeners
如果你不想ToolBarManager來(lái)創(chuàng)建toolbar的話,可以手動(dòng)創(chuàng)建,需要用到ToolBar和ToolItem類.
Toolbar
是一個(gè)composite control,包含多個(gè)ToolItems.Toolbar由多個(gè)小圖標(biāo)按鈕組成,一般是16-by-16bitmap圖片。每個(gè)按鈕都對(duì)應(yīng)一個(gè)ToolItem。Toolbar可以是水平的也可以是垂直的,默認(rèn)為水平
ToolItem
每一個(gè)ToolItem都有一個(gè)圖片,如果沒(méi)有,默認(rèn)為紅色方塊。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.
三種類型的Combo control:
1.Simple:默認(rèn)類型,一個(gè)可編輯的text field和一個(gè)供選擇的list
2.Drop-down:下拉列表,文本框可編輯
3.Read-only:文本框不可編輯的下拉列表,可用select( 0 )來(lái)將其默認(rèn)選中列表中的首項(xiàng)。
以上三種類型可在構(gòu)造函數(shù)中通過(guò)STYLE.*來(lái)設(shè)置。
先要將org.eclipse.text_x.y.z和org.eclipse.jface.text_x.y.z加到classpath
兩個(gè)重要的接口:IDocument和ITextViewer。JFace為其提供了默認(rèn)的實(shí)現(xiàn)。
一個(gè)IDocument的實(shí)例持有被編輯的真實(shí)的文本信息。它的主要實(shí)現(xiàn)是Document類。AbstractDocument提供了部分實(shí)現(xiàn),你可通過(guò)繼承它來(lái)添加自己的實(shí)現(xiàn)。IDocument允許通過(guò)IDocumentListener接口來(lái)獲取內(nèi)容編輯的通知。
IDocument還提供了以下功能
Positions
可以給每一個(gè)text區(qū)域分配一個(gè)記號(hào)來(lái)作為它的Position。當(dāng)被指定給某個(gè)ducument時(shí)一個(gè)Position對(duì)象有an offset and a length of text。如果document的text被更新的話,Position也會(huì)同步更新,所以他永遠(yuǎn)都是指向同一段文字。Position類本身提供了一些基本的功能,可通過(guò)繼承他來(lái)完善更多有用的功能。
Partition content types
每個(gè)document由一個(gè)或多個(gè)partitions組成,通過(guò)ITypedRegion接口來(lái)表現(xiàn)。每一個(gè)partition可以有各自的內(nèi)容類型,如plain text, rich text, or HTML。要使用它,你要?jiǎng)?chuàng)建一個(gè)IDocumentPartitioner然后assign給你的document,然后document的partitioner就會(huì)負(fù)責(zé)響應(yīng)對(duì)指定位置內(nèi)容類型的查詢,它必須通過(guò)實(shí)現(xiàn)computePartitioning()來(lái)返回包含此document中所有ITypedRegions的一個(gè)數(shù)組。不需要實(shí)現(xiàn)你自己的document partitioner。如果沒(méi)有創(chuàng)建,整個(gè)document就是一個(gè)區(qū)域,類型為IDocument.DEFAULT_CONTENT_TYPE。
Searching
IDocument通過(guò)search()提供了搜索的功能。不支持regular expressions or other patterns,但提供了search start location,direction, and case sensitivity and whether to match whole words only.
ITextViewer將一個(gè)標(biāo)準(zhǔn)的text widget轉(zhuǎn)換成一個(gè)基于document的text widget
ITextViewer的默認(rèn)實(shí)現(xiàn)是TextViewer,它使用StyledText來(lái)顯示數(shù)據(jù)。ITextViewer支持text modifications的listener,也支持visual events(如改變viewport,即text的當(dāng)前可視區(qū)域)的監(jiān)聽器。
雖然作為ITextViewer的默認(rèn)應(yīng)用,如果你想要修改顯示,TextViewer允許你直接accessStyledText,但建議你使用TextPresentation,因?yàn)樗梢允占撐臋n中帶有的各個(gè)不同的StyleRanges。
ITextViewer還支持很多不同類型的插件,可用來(lái)修改widget的行為??梢员籧ustomized的功能有:
1.通過(guò)IUndoManager來(lái)支持undo
2.通過(guò)ITextDoubleClickStrategy來(lái)支持對(duì)鼠標(biāo)雙擊的處理
3.通過(guò)IAutoIndentStrategy來(lái)支持文本的自動(dòng)縮進(jìn)
4.通過(guò)ITextHover來(lái)實(shí)現(xiàn),當(dāng)鼠標(biāo)停留在document的一個(gè)section上時(shí),顯示text.
要使用上述插件,你需要分配一個(gè)適當(dāng)?shù)慕涌趯?shí)例給text viewer,然后調(diào)用activatePlugins().
如下列出了org.eclipse.jface.text的子包及其作用
| |||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
---|---|---|---|---|---|---|---|---|---|
26 | 27 | 28 | 29 | 30 | 31 | 1 | |||
2 | 3 | 4 | 5 | 6 | 7 | 8 | |||
9 | 10 | 11 | 12 | 13 | 14 | 15 | |||
16 | 17 | 18 | 19 | 20 | 21 | 22 | |||
23 | 24 | 25 | 26 | 27 | 28 | 29 | |||
30 | 1 | 2 | 3 | 4 | 5 | 6 |