增加一些內(nèi)容
現(xiàn)在我們已經(jīng)有一個(gè)view能夠成功運(yùn)行了.我們可以往里面增加一些內(nèi)容.Eclipse forms有一個(gè)body,我們可以這樣創(chuàng)建內(nèi)容.
public void createPartControl(Composite parent) {
toolkit = new FormToolkit(parent.getDisplay());
form = toolkit.createForm(parent);
form.setText("Hello, Eclipse Forms");
GridLayout layout = new GridLayout();
form.getBody().setLayout(layout);
Hyperlink link = toolkit.createHyperlink(form.getBody(),
"Click here.", SWT.WRAP);
link.addHyperlinkListener(new HyperlinkAdapter() {
public void linkActivated(HyperlinkEvent e) {
System.out.println("Link activated!");
}
});
}
form的body是標(biāo)題下面的可用空間.因?yàn)檫@個(gè)空間是一個(gè)SWT Composite,它能做為其它組件的parent.在上面的代碼里,
我們?yōu)閎ody設(shè)置了layout,
然后創(chuàng)建了一個(gè)超鏈接.超鏈接是由Eclipse Forms提供的為數(shù)不多的組件之一.我們可以為超鏈接
增加監(jiān)聽器,這樣能夠在用戶點(diǎn)擊它時(shí)做出反應(yīng).
升級后的視圖應(yīng)該看起來象這樣:
圖3:一個(gè)有超鏈接的簡單form.
超鏈接組(Hyperlink Groups)
Form tookit有一個(gè)"超鏈接組"對象.每個(gè)創(chuàng)建出的超鏈接都加入這個(gè)組對象中.超鏈接為多個(gè)角色服務(wù).它們定義了這個(gè)組中所有超鏈接在正常、hover、激活不同狀態(tài)下的顏色.它們根據(jù)小組中鏈接不同的狀態(tài)來改變顏色.它們根據(jù)小組中鏈接不同的狀態(tài)來改變下劃線風(fēng)格.
當(dāng)你要改變超鏈接組對象的默認(rèn)設(shè)置時(shí),可以通過toolkit的getHyperlinkGroup()方法來獲得超鏈接組對象.
創(chuàng)建普通組件
Eclipse Forms的一個(gè)設(shè)計(jì)目標(biāo)就是讓能夠在編輯器/視圖中創(chuàng)建普通SW
T組件.因?yàn)閒orm的body是一個(gè)普通composite,你能夠在它里面使用任何layout和組件.但是,記住"原生的"SWT組件有一個(gè)組件背景.我們現(xiàn)在通過它們的構(gòu)造方法創(chuàng)建一些組件.
layout.numColumns = 2;
GridData gd = new GridData();
gd.horizontalSpan = 2;
link.setLayoutData(gd);
Label label = new Label(form.getBody(), SWT.NULL);
label.setText("Text field label:");
Text text = new Text(form.getBody(), SWT.BORDER);
text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Button button = new Button(form.getBody(), SWT.CHECK);
button.setText("An example of a checkbox in a form");
gd = new GridData();
gd.horizontalSpan = 2;
button.setLayoutData(gd);
現(xiàn)在我們使用了兩列,并且創(chuàng)建了一個(gè)標(biāo)簽(label),一個(gè)文本框(text field)和一個(gè)復(fù)選框(checkbox).結(jié)果如下:

圖4:一個(gè)擁有直接用它們的構(gòu)造器創(chuàng)建出的SWT組件的form
這張圖片怎么回事?我們創(chuàng)建的組件的背景直接和系統(tǒng)窗口背景相匹配
,而不是和form的背景匹配.另外,文本框看起來還好是因?yàn)檫@張截圖是在Windows XP下截的.在其它操作系統(tǒng)上,它會(huì)看起來是有一個(gè)3D邊框的空白條.為了解決這個(gè)問題,我們會(huì)用toolkit的工廠方法來創(chuàng)建這些組件:
Label label = toolkit.createLabel(form.getBody(), "Text field label:");
Text text = toolkit.createText(form.getBody(), "");
text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Button button = toolkit.createButton(form.getBody(), "A checkbox in a form", SWT.CHECK);
gd = new GridData();
gd.horizontalSpan = 2;
button.setLayoutData(gd);
這個(gè)視圖現(xiàn)在會(huì)看來更好些了:

圖5:一個(gè)擁有用form toolkit的工廠方法創(chuàng)建出的SWT組件的form
由form toolkit提供的工廠方法是為了方便.Toolkit沒有函蓋所有情況,甚至是SWT組件集合,而且明顯沒有為你可能有的自己定制的組件提供這一便利.當(dāng)你需要使一個(gè)SWT組件與form統(tǒng)一時(shí),你應(yīng)該使用一個(gè)方法:FormToolkit.adapt(Control control, boolean trackFocus, boolean trackKeyboard).所有的工廠方法各自分別調(diào)用了這個(gè)適配方法.
達(dá)到"平滑"的視覺效果
一個(gè)在PDE編輯器中Eclipse Forms的可看出的屬性是組件的"平滑"視覺效果.以前所有沒有3D邊框的組件在窗口中看起來不錯(cuò),但是在編輯器或視圖中就不行.這個(gè)支持寫在FormToolkit類中.但是,在一些系統(tǒng)上它是通過一些定制達(dá)到的.舉個(gè)例子,看一下這張從PDE編輯器(2.1版本)中的截圖:
圖片6:Eclipse 2.1中Eclipse Forms的平滑視覺效果.
象表格,文本類,復(fù)選框等,是加上一個(gè)平滑的1個(gè)象素寬的邊框.這些邊框不是來自組件自己(SWT.BORDER風(fēng)格沒有用到).另外,如果設(shè)置一下,tookit會(huì)為每個(gè)組件的parent增加一個(gè)paint監(jiān)聽器,在paint事件發(fā)生時(shí)為組件加上邊框.要想這樣的話,你需要為你創(chuàng)建的象文本,表格,樹等組件的每個(gè)composite調(diào)用paintBordersFor(parent).每個(gè)parent只需要調(diào)用一次方法就足夠了:不需要為每個(gè)組件這樣調(diào)用.
Form toolkit知道哪個(gè)組件需要一個(gè)定制的邊框.但是,你可能新創(chuàng)建了一個(gè)不在原來名單中的組件,它也需要一個(gè)邊框.你可以通過象下面這樣的代碼給toolkit一個(gè)提示:
Control myControl = new MyControl(parent);
myControl.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
// or myControl.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TREE_BORDER);
toolkit.paintBordersFor(parent);
你可以在上面這張圖中看出,象樹和表格這樣的"結(jié)構(gòu)化(structural)"的組件有和文本區(qū)域不同的邊框風(fēng)格并且你可以選擇和你的組件相符合的那個(gè).注意用toolkit的工廠方法創(chuàng)建出的組件不需要這樣做.
因?yàn)镋clipse 3.0和在Windows XP上,當(dāng)javaw.exe.manifest文件在Java虛擬機(jī)bin文件夾中時(shí),沒有邊框產(chǎn)生出來.(這篇文章里我所有截圖都是在Windows XP下截的).這個(gè)文件--你可以在 SWT home page上下載--告訴toolkit為本地組件使用XP皮膚.用XP皮膚,象文本,表格和樹是已經(jīng)平滑的并且不需要再去調(diào)整.為了讓你的代碼擁有可移植性,你可以總是調(diào)用paintBordersFor(Composite)方法,讓toolkit去根據(jù)不同操作系統(tǒng)來決定該怎么做.
定制布局(Custom layouts)
Eclipse Forms在SWT layout的基礎(chǔ)上增加了兩個(gè)新的layout.這些layout繼承了SWT Layout基類并能夠在任何SWT composite上使用,但是一般都是和Eclipse Forms聯(lián)合使用的.
TableWrapLayout
現(xiàn)在我們知道如何來組合一個(gè)form,讓我們先給一個(gè)懸念.我們會(huì)改變那個(gè)超鏈接文本使它加長一些:
link.setText("This is an example of a form that is much longer "+
"and will need to wrap.");
讓我們看看結(jié)果:

圖片7:一個(gè)使用GridLayout的form
發(fā)生什么事了?記住我們使用的是GridLayout.當(dāng)它問這個(gè)超鏈接組件來計(jì)算它大小時(shí),超鏈接告訴它文字在單獨(dú)行里需要的長度.雖然我們告訴組件去包裹(wrap),它并沒有這樣做因?yàn)镚ridLayout需要組件返回它的長度.超連接組件--和其它象Label一樣的SWT組件,可以通過你傳遞它數(shù)值來決定長和寬,但是GridLayout不會(huì)向組件傳遞數(shù)值參數(shù).
我們需要的是一個(gè)象HTML表格一樣的layout.我們希望內(nèi)容去試圖配合提供的客戶空間,并且一行行地疊加.Eclipse Forms提供了一個(gè)這樣的layout叫TableWrapLayout.GridLayout和TableWrapLayout之間有許多共同點(diǎn).都是用表格來組織parent的children.都有l(wèi)ayout data來告訴layout如何對待每個(gè)組件.都能夠在需要占據(jù)所有空間時(shí)等接受組件的提示.
但是,它們在布局時(shí)完全不同.TableWrapLayout從列開始.它計(jì)算每列的最小的,合適的,最大的寬度并用這個(gè)信息來占據(jù)空間.它也試圖盡可能地公平地在各列間分隔,這樣有些組件就沒有多余的空間.
讓我們使用TableWrapLayout來重新更改例子(更改處高亮顯示):
public void createPartControl(Composite parent) {
toolkit = new FormToolkit(parent.getDisplay());
form = toolkit.createForm(parent);
form.setText("Hello, Eclipse Forms");
TableWrapLayout layout = new TableWrapLayout();
form.getBody().setLayout(layout);
Hyperlink link = toolkit.createHyperlink(form.getBody(),"Click here.", SWT.WRAP);
link.addHyperlinkListener(new HyperlinkAdapter() {
public void linkActivated(HyperlinkEvent e) {
System.out.println("Link activated!");
}
});
link.setText("This is an example of a form that is much longer and will need to wrap.");
layout.numColumns = 2;
TableWrapData td = new TableWrapData();
td.colspan = 2;
link.setLayoutData(td);
Label label = toolkit.createLabel(form.getBody(), "Text field label:");
Text text = toolkit.createText(form.getBody(), "");
td = new TableWrapData(TableWrapData.FILL_GRAB);
text.setLayoutData(td);
Button button = toolkit.createButton(form.getBody(), "A checkbox in a form", SWT.CHECK);
td = new TableWrapData();
td.colspan = 2;
button.setLayoutData(td);
}
我們用了GridData相同的概念.一些變量擁有不同的名字(舉個(gè)例子,colspan和rowspan,align和valign取自HTML TABLE的屬性),但是你可以做相同的事--創(chuàng)建一個(gè)超鏈接和按鈕占據(jù)兩列的格子.因?yàn)榭瞻?margins)和GridLayout是相同的,結(jié)果會(huì)看起來一樣,除了超鏈接現(xiàn)在會(huì)包裹起來:

圖片8:一個(gè)使用TableWrapLayout的form
TableWrapLayout和GridLayout的一個(gè)主要的不同點(diǎn)是你應(yīng)該停止去計(jì)算垂直的空間.在GridLayout里,你一般會(huì)讓"不易變形的(rigid)"組件用自然的位置和大小并讓"可伸縮的(flexible)"組件去占據(jù)水平或垂直的空間.相反,TableWrapLayout是從上往下工作的,并且它容下所有的組件,它的工作是完全的.占據(jù)水平空間的概念還存在(象上面展示一樣).但是,垂直方向上,你只能在單元(cell)比組件高時(shí)選擇FILL單元,或選擇TOP,MIDDLE或BOTTOM垂直對齊.
你也許會(huì)注意到一個(gè)地方和剛剛說的不符:TableWrapLayout仍然有一個(gè)grabVertical變量.但是,這里這個(gè)變量在這里有明確的目的:當(dāng)一個(gè)設(shè)置了高度的組件占多行時(shí),它的高度會(huì)給出一個(gè)條件就是垂直dimension已經(jīng)知道了,組件需要去除它所在的多個(gè)單元之間的多余空間.
為了用TableWrapLayout有好的結(jié)果,確定組件可以接近風(fēng)格(SWT.WRAP).Eclipse Froms提供的組合定制組件能夠在box外面包裹.這是通過實(shí)現(xiàn)ILayoutExtension接口實(shí)現(xiàn)的:
public interface ILayoutExtension {
/**
* Computes the minimum width of the parent. All widgets capable of word
* wrapping should return the width of the longest word that cannot be
* broken any further.
*
* @param parent the parent composite
* @param changed <code>true</code> if the cached information should be
* flushed, <code>false</code> otherwise.
* @return the minimum width of the parent composite
*/
public int computeMinimumWidth(Composite parent, boolean changed);
/**
* Computes the maximum width of the parent. All widgets capable of word
* wrapping should return the length of the entire text with wrapping
* turned off.
*
* @param parent the parent composite
* @param changed <code>true</code> if the cached information
* should be flushed, <code>false</code> otherwise.
* @return the maximum width of the parent composite
*/
public int computeMaximumWidth(Composite parent, boolean changed);
}
TableWrapLayout本身實(shí)現(xiàn)了這個(gè)接口,這樣讓它處理當(dāng)composites的layout是這個(gè)composite的parent的children的情況.另外的兩個(gè)方法能夠計(jì)算兩種極端情況--當(dāng)所有組件盡可能寬地布滿時(shí)的顯然的最小寬度和最大寬度.兩者的不同是使列之間的多余空間盡可能小時(shí)貢獻(xiàn)出公平的空間.
讓我們看清楚貢獻(xiàn)空間是怎樣的.我們會(huì)推薦我們到現(xiàn)在為止寫的代碼并象下面這樣做出修改:
layout.numColumns = 3;
Label label;
TableWrapData td;
label = toolkit.createLabel(form.getBody(),
"Some text to put in the first column", SWT.WRAP);
label = toolkit.createLabel(form.getBody(),
"Some text to put in the second column and make it a bit "+
"longer so that we can see what happens with column "+
distribution. This text must be the longest so that it can "+
"get more space allocated to the columns it belongs to.",
SWT.WRAP);
td = new TableWrapData();
td.colspan = 2;
label.setLayoutData(td);
label = toolkit.createLabel(form.getBody(),
"This text will span two rows and should not grow the column.",
SWT.WRAP);
td = new TableWrapData();
td.rowspan = 2;
label.setLayoutData(td);
label = toolkit.createLabel(form.getBody(),
"This text goes into column 2 and consumes only one cell",
SWT.WRAP);
label.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB));
label = toolkit.createLabel(form.getBody(),
"This text goes into column 3 and consumes only one cell too",
SWT.WRAP);
label.setLayoutData(new TableWrapData(TableWrapData.FILL));
label = toolkit.createLabel(form.getBody(),
"This text goes into column 2 and consumes only one cell",
SWT.WRAP);
label.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB));
label = toolkit.createLabel(form.getBody(),
"This text goes into column 3 and consumes only one cell too",
SWT.WRAP);
label.setLayoutData(new TableWrapData(TableWrapData.FILL));
form.getBody().setBackground(form.getBody().getDisplay().
getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
這個(gè)創(chuàng)建了一些有不同長度文本的label.有些labels占據(jù)多列,有些占據(jù)多行.為了讓測試更加簡單,
我們把form的背景設(shè)置為組件背景,這樣單元能夠更簡單看出來.當(dāng)我們運(yùn)行例子,我們會(huì)得到下面的樣子:

圖片9:TableWrapLayout留下的多余空間
關(guān)鍵之處在于組件最小寬度和最大寬度相比較時(shí).相差越多,結(jié)果越明顯,會(huì)看到列中有很大的縫隙.占據(jù)的寬度是組件所需要的最小的寬度.注意第3列比第2列稍微寬一點(diǎn)點(diǎn),這是因?yàn)榈?列中的文字長度比第2列中文字要長點(diǎn).如果需要閱讀布局的相關(guān)理論,可以去這里W3C recommendations for HTML table auto-layout.
ColumnLayout
Eclipse Forms另外一個(gè)定制的layout是SWT RowLayout的變種.如果我們把RowLayout上的children垂直放置時(shí)--按列-并且使同列中的所有組件擁有相同的寬度,我們會(huì)由組件的寬度得到多個(gè)列.但是,最后一列顯然不是被填滿的--這由組件的個(gè)數(shù)決定.如果在form中,我們會(huì)仍然看到所有組件在一列中,因?yàn)镽owLayout不能夠"垂直" 包裹.如果我們用GridLayout相替代的話,列的數(shù)量由我們自己決定.
在更加復(fù)雜的forms中我們需要列的數(shù)量按情況變化.換句話來說,我們希望數(shù)字按照form的寬度來改變--有可能需要更多的列,當(dāng)寬度減小時(shí)則把數(shù)字減小.而且我們希望所有列的長度象報(bào)紙布局一樣相同.這些要求都能夠通過ColumnLayout來達(dá)到.
與TableWrapLayout相比,ColumnLayout更加簡單.不需要復(fù)雜的設(shè)置.唯一需要你設(shè)置的就是列數(shù)的范圍,默認(rèn)是1到3.下面的例子演示了一個(gè)使用ColumnLayout的有許多段落(sections)的form.初始時(shí),只需要兩列就可以放置所有段落了.如果我們把編輯器變窄一點(diǎn),layout會(huì)使它們在同一列中.
圖片10:使用ColumnLayout的所有按列排列的段落
.layout開始是兩列,但是按照空間的改變變成了一列.
轉(zhuǎn)自:http://blog.csdn.net/starshus/archive/2006/02/07/593785.aspx