分享
 
 
 

Eclipse Forms: 为胖客户端做的漂亮UI(翻译,第二部分)

王朝java/jsp·作者佚名  2006-02-14
窄屏简体版  字體: |||超大  

增加一些内容

现在我们已经有一个view能够成功运行了.我们可以往里面增加一些内容.Eclipse forms有一个body,我们可以这样创建内容.

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是标题下面的可用空间.因为这个空间是一个SWT Composite,它能做为其它组件的parent.在上面的代码里,

我们为body设置了layout,
然后创建了一个超链接.超链接是由Eclipse Forms提供的为数不多的组件之一.我们可以为超链接
增加监听器,这样能够在用户点击它时做出反应.

升级后的视图应该看起来象这样:

图3:一个有超链接的简单form.

超链接组(Hyperlink Groups)

Form tookit有一个"超链接组"对象.每个创建出的超链接都加入这个组对象中.超链接为多个角色服务.它们定义了这个组中所有超链接在正常、hover、激活不同状态下的颜色.它们根据小组中链接不同的状态来改变颜色.它们根据小组中链接不同的状态来改变下划线风格.

当你要改变超链接组对象的默认设置时,可以通过toolkit的getHyperlinkGroup()方法来获得超链接组对象.

创建普通组件

Eclipse Forms的一个设计目标就是让能够在编辑器/视图中创建普通SWT组件.因为form的body是一个普通composite,你能够在它里面使用任何layout和组件.但是,记住"原生的"SWT组件有一个组件背景.我们现在通过它们的构造方法创建一些组件.

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

现在我们使用了两列,并且创建了一个标签(label),一个文本框(text field)和一个复选框(checkbox).结果如下:

图4:一个拥有直接用它们的构造器创建出的SWT组件的form

这张图片怎么回事?我们创建的组件的背景直接和系统窗口背景相匹配,而不是和form的背景匹配.另外,文本框看起来还好是因为这张截图是在Windows XP下截的.在其它操作系统上,它会看起来是有一个3D边框的空白条.为了解决这个问题,我们会用toolkit的工厂方法来创建这些组件:

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

这个视图现在会看来更好些了:

图5:一个拥有用form toolkit的工厂方法创建出的SWT组件的form

由form toolkit提供的工厂方法是为了方便.Toolkit没有函盖所有情况,甚至是SWT组件集合,而且明显没有为你可能有的自己定制的组件提供这一便利.当你需要使一个SWT组件与form统一时,你应该使用一个方法:FormToolkit.adapt(Control control, boolean trackFocus, boolean trackKeyboard).所有的工厂方法各自分别调用了这个适配方法.

达到"平滑"的视觉效果

一个在PDE编辑器中Eclipse Forms的可看出的属性是组件的"平滑"视觉效果.以前所有没有3D边框的组件在窗口中看起来不错,但是在编辑器或视图中就不行.这个支持写在FormToolkit类中.但是,在一些系统上它是通过一些定制达到的.举个例子,看一下这张从PDE编辑器(2.1版本)中的截图:

图片6:Eclipse 2.1中Eclipse Forms的平滑视觉效果.

象表格,文本类,复选框等,是加上一个平滑的1个象素宽的边框.这些边框不是来自组件自己(SWT.BORDER风格没有用到).另外,如果设置一下,tookit会为每个组件的parent增加一个paint监听器,在paint事件发生时为组件加上边框.要想这样的话,你需要为你创建的象文本,表格,树等组件的每个composite调用paintBordersFor(parent).每个parent只需要调用一次方法就足够了:不需要为每个组件这样调用.

Form toolkit知道哪个组件需要一个定制的边框.但是,你可能新创建了一个不在原来名单中的组件,它也需要一个边框.你可以通过象下面这样的代码给toolkit一个提示:

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

你可以在上面这张图中看出,象树和表格这样的"结构化(structural)"的组件有和文本区域不同的边框风格并且你可以选择和你的组件相符合的那个.注意用toolkit的工厂方法创建出的组件不需要这样做.

因为Eclipse 3.0和在Windows XP上,当javaw.exe.manifest文件在Java虚拟机bin文件夹中时,没有边框产生出来.(这篇文章里我所有截图都是在Windows XP下截的).这个文件--你可以在 SWT home page上下载--告诉toolkit为本地组件使用XP皮肤.用XP皮肤,象文本,表格和树是已经平滑的并且不需要再去调整.为了让你的代码拥有可移植性,你可以总是调用paintBordersFor(Composite)方法,让toolkit去根据不同操作系统来决定该怎么做.

定制布局(Custom layouts)

Eclipse Forms在SWT layout的基础上增加了两个新的layout.这些layout继承了SWT Layout基类并能够在任何SWT composite上使用,但是一般都是和Eclipse Forms联合使用的.

TableWrapLayout

现在我们知道如何来组合一个form,让我们先给一个悬念.我们会改变那个超链接文本使它加长一些:

link.setText("This is an example of a form that is much longer "+

"and will need to wrap.");

让我们看看结果:

图片7:一个使用GridLayout的form

发生什么事了?记住我们使用的是GridLayout.当它问这个超链接组件来计算它大小时,超链接告诉它文字在单独行里需要的长度.虽然我们告诉组件去包裹(wrap),它并没有这样做因为GridLayout需要组件返回它的长度.超连接组件--和其它象Label一样的SWT组件,可以通过你传递它数值来决定长和宽,但是GridLayout不会向组件传递数值参数.

我们需要的是一个象HTML表格一样的layout.我们希望内容去试图配合提供的客户空间,并且一行行地叠加.Eclipse Forms提供了一个这样的layout叫TableWrapLayout.GridLayout和TableWrapLayout之间有许多共同点.都是用表格来组织parent的children.都有layout data来告诉layout如何对待每个组件.都能够在需要占据所有空间时等接受组件的提示.

但是,它们在布局时完全不同.TableWrapLayout从列开始.它计算每列的最小的,合适的,最大的宽度并用这个信息来占据空间.它也试图尽可能地公平地在各列间分隔,这样有些组件就没有多余的空间.

让我们使用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相同的概念.一些变量拥有不同的名字(举个例子,colspan和rowspan,align和valign取自HTML TABLE的属性),但是你可以做相同的事--创建一个超链接和按钮占据两列的格子.因为空白(margins)和GridLayout是相同的,结果会看起来一样,除了超链接现在会包裹起来:

图片8:一个使用TableWrapLayout的form

TableWrapLayout和GridLayout的一个主要的不同点是你应该停止去计算垂直的空间.在GridLayout里,你一般会让"不易变形的(rigid)"组件用自然的位置和大小并让"可伸缩的(flexible)"组件去占据水平或垂直的空间.相反,TableWrapLayout是从上往下工作的,并且它容下所有的组件,它的工作是完全的.占据水平空间的概念还存在(象上面展示一样).但是,垂直方向上,你只能在单元(cell)比组件高时选择FILL单元,或选择TOP,MIDDLE或BOTTOM垂直对齐.

你也许会注意到一个地方和刚刚说的不符:TableWrapLayout仍然有一个grabVertical变量.但是,这里这个变量在这里有明确的目的:当一个设置了高度的组件占多行时,它的高度会给出一个条件就是垂直dimension已经知道了,组件需要去除它所在的多个单元之间的多余空间.

为了用TableWrapLayout有好的结果,确定组件可以接近风格(SWT.WRAP).Eclipse Froms提供的组合定制组件能够在box外面包裹.这是通过实现ILayoutExtension接口实现的:

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本身实现了这个接口,这样让它处理当composites的layout是这个composite的parent的children的情况.另外的两个方法能够计算两种极端情况--当所有组件尽可能宽地布满时的显然的最小宽度和最大宽度.两者的不同是使列之间的多余空间尽可能小时贡献出公平的空间.

让我们看清楚贡献空间是怎样的.我们会推荐我们到现在为止写的代码并象下面这样做出修改:

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

这个创建了一些有不同长度文本的label.有些labels占据多列,有些占据多行.为了让测试更加简单,

我们把form的背景设置为组件背景,这样单元能够更简单看出来.当我们运行例子,我们会得到下面的样子:

图片9:TableWrapLayout留下的多余空间

关键之处在于组件最小宽度和最大宽度相比较时.相差越多,结果越明显,会看到列中有很大的缝隙.占据的宽度是组件所需要的最小的宽度.注意第3列比第2列稍微宽一点点,这是因为第3列中的文字长度比第2列中文字要长点.如果需要阅读布局的相关理论,可以去这里W3C recommendations for HTML table auto-layout.

ColumnLayout

Eclipse Forms另外一个定制的layout是SWT RowLayout的变种.如果我们把RowLayout上的children垂直放置时--按列-并且使同列中的所有组件拥有相同的宽度,我们会由组件的宽度得到多个列.但是,最后一列显然不是被填满的--这由组件的个数决定.如果在form中,我们会仍然看到所有组件在一列中,因为RowLayout不能够"垂直" 包裹.如果我们用GridLayout相替代的话,列的数量由我们自己决定.

在更加复杂的forms中我们需要列的数量按情况变化.换句话来说,我们希望数字按照form的宽度来改变--有可能需要更多的列,当宽度减小时则把数字减小.而且我们希望所有列的长度象报纸布局一样相同.这些要求都能够通过ColumnLayout来达到.

与TableWrapLayout相比,ColumnLayout更加简单.不需要复杂的设置.唯一需要你设置的就是列数的范围,默认是1到3.下面的例子演示了一个使用ColumnLayout的有许多段落(sections)的form.初始时,只需要两列就可以放置所有段落了.如果我们把编辑器变窄一点,layout会使它们在同一列中.

图片10:使用ColumnLayout的所有按列排列的段落.layout开始是两列,但是按照空间的改变变成了一列.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有