像其它的layout类一样,FormLayout用的data类是:FormData。FormData用另外一 个类来控制窗口小部件的大小和位置: FormAttachment.一个FormData最多用4个FormAttachment,它们分别对应这个小部件的4个面:顶部,底部,左边和右 边。FormAttachment定义了小部件在parent composite或是这个composite里其它部件的位置。
FormAttachment计算位置和大小的方法:
y=ax+b
在这个等式中,在数学上y代表的是纵坐标,x是横坐标值.a是斜率,b是偏移量.按照FormAttachment的规则,y是 高,x是宽度,a是一个相对其它部件的百分率,b是偏移量.FormAttachment实例中的每个数据成员分别代表这些值.
以下(表一)是FormAttachment的数据成员表和相应的意思:
表 一:FormAttachment数据成员
Attribute |
Description |
---|---|
int alignment |
指定是以另外一个部件的哪一边为基准的.可能的值是:SWT.TOP , SWT.CENTER , 和 SWT.BOTTOM.默认是以最近的一边为基准. |
Control control |
指定 FormAttachment是以哪个部件为参照物. |
int denominator |
指定分母.默认值为100 |
int numerator |
指定分子 |
int offset |
指定离 composite边界或部件的边界的偏移量.单位是象素. |
FormAttachment 拥有5个构造函数,没有一个是空的,它们如下表(表二)所示:
表二:FormAttachment 的 构造函数:
Constructor |
Description |
---|---|
FormAttachment(Control control) |
以另外的某个部件为参照物. |
FormAttachment(Control control, int offset) |
以另外的某个部件为参照物,加上偏移量. |
FormAttachment(Control control, int offset, int alignment) |
以另外的某个部件为参照物,加上偏移量和alignment |
FormAttachment(int numerator) |
设定分子.分母为100,没有偏移量 |
FormAttachment(int numerator, int offset) |
指定分子和偏移量和 100的分母 |
FormAttachment(int numerator, int denominator, int offset) |
特定的分子,分母,偏移 量 |
FormData最多包含4个FormAttachment 实例,每个对应了与它联系的部件的一边.另外,FormData也可以指定宽和高.表四列出了FormData的数据成员:
Attribute |
Description |
---|---|
FormAttachment bottom |
The FormAttachment corresponding to the bottom side of the control. 这个FormAttachment 用 来指定部件的底部位置 |
int height |
这个部件的高度.单位为象素. |
FormAttachment left |
这个FormAttachment 用来指定部件的左部位置 |
FormAttachment right |
这个FormAttachment 用来指定部件的右部位置 |
FormAttachment top |
这个FormAttachment 用来指定部件的顶部位置 |
int width |
这个部件的宽度.单位为 象素. |
当你生成一个FormData对象,你可以自己传给它宽和高的值.如果你没有指定FormAttachment 对 象,部件会自动以parent composite的上边界和左边为起始边界.如果你这样定义了多个部件,它们会都在composite的左上角.
FormLayout 有 两个数据成员 marginHeight和marginWidth,用来以象素为单位来指定大小.它们用来指定包围composite里所有内容的空白. marginHeight对应的是顶部和底部的空白大小,marginWidth对应的是左边和右边的空白大小.空白的默认值是0.
以上的话如果你看得不大懂也没有关系,我们按照具体的例子来看就知道了.
用到FormLayout的最简单的例子就是一个窗口里一个按钮,并且不用 FormData.
import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class TestFormLayout { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setLayout(new FormLayout()); new Button(shell, SWT.PUSH).setText("Button"); shell.pack(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); } }
通过上述代码我们可以简单的在一个shell上设置一个button,并且button距离整个界面的其他的边界距离为0。
我们可以通过设定marginHeight和marginWidth值改变周围的空白,即距离边界的距离.
代码象这样:
FormLayout layout = new FormLayout(); layout.marginHeight = 5; layout.marginWidth = 10; shell.setLayout(layout);
但是,只有用FormData和FormAttachment你才能做更多的事.
试着使 用FormData,但是不用FormAttachment s,FormData有公共成员属性 height和width用来改变按钮的大小.
Button button = new Button(shell, SWT.PUSH); button.setText("Button"); FormData data = new FormData(); data.height = 50; data.width = 50; button.setLayoutData(data);
按钮在窗口中的位置是静态的,也就是说改变窗口的大小不影响按钮的位置.
我们举个例子,比如说,你希望这个按钮始终离窗口的右边界50个象素的话,
你必须在你刚刚产生的FormData上添加一个FormAttachment.
因为你现在要指定这个按钮的右边的具体情况了.所以你现在要设置FormData的right属性,
还记得FormData的right属性是一个FormAttachment对象吧.
当与parent composite产生联系时,如果是顶部和左边的话,分子设置为0,
如果是顶部和右边的话,分子设置为100,分别代表了0%和100%.可以在
构造函数中设置分子.我们现在把分子设置为100,偏移量设置为-50.
我们不需要设置分母,因为它的默认大小是100.代码象这样:
data.right = new FormAttachment(100, -50);
现在编译并运行程序,按钮离右边刚好50个象素.缩小窗口也不会有任何影响,按钮离右边始终是50象素.
现在按钮总是维持它离右边50个象素,
但是我们需要它始终保持位置不变,并且随着窗口的伸缩而伸缩.要实现这个要求,我们必须设置它的左边,
所以可以这样实现:
data.left = new FormAttachment(0, 10);
把分子的值设置为0表示它是以窗口的最左边来计算偏移量的.
偏移量设置为10表示它始终离窗口最左边10个象素.
重新编译运行程序,初始界面好象和刚刚差不多,
但是改变窗口大小就可以看到按钮离窗口左边的大小始终没有改变.
离左边和离右边的值已经设置好了,所以它的宽度自然也定下来了,我们可以把原来 FormData设置的按钮宽度那行代码删掉了.
现在有点熟悉了 吧,现在我们把按钮联系到窗口的顶部和底部.我们可以把它放到离窗口顶部25%的距离.我们可以简单的表示为1/4,而不是0.25让分母保持为默认值 (这样也可以).我们把偏移量设置为0.加上这句代码:
data.top = new FormAttachment(1, 4, 0);
现在按钮保持与顶部1/4的距离了.无论怎么改变窗口大小都是1/4。
让我们在这个按钮下面再添加一个按钮.我们把这个按钮布置在现在的按钮下面,添加按钮的顶部在现在的按钮的底部下面5个象 素.并且左边和右边分别和现在的按钮对齐.从下面的代码开始:
Button button2 = new Button(shell, SWT.PUSH); button2.setText("Button 2");
然后我们产生一个FormData对象,设置它的bottom成员.我们把分子设置为0,偏移量为0。
data = new FormData(); button2.setLayoutData(data); data.bottom = new FormAttachment(100, 0);
为了以现在的按钮为标准来算偏移量,我们只需要把第一个按钮传个FormAttachment的构造函数就可以了,那么现
在就不是以窗口边界来计算,而是以传递给它的按钮来计算了.
我们要把这个按钮加到以有按钮的下面5个象素处,所以偏移量是5.
data.top = new FormAttachment(button, 5);
我们不需要设置为以按钮的底部为界,因为默认情况下,边界被自动设是离这个按钮最近的边界.
因为我们指定的FormAttachment是用来指定新按钮的顶部的,
而且新按钮是在第一个按钮后面加上去的,新按钮离第一个按钮的地方最近的就是底部.
你可能就用同样的构造函数来设置新按钮的左边界,甚至就用只需要一个Control对象的构造函数,
因为偏移量是0.象这样:
data.left = new FormAttachment(button);
但是这句代码是以第一个按钮的右边为基准来计算的,如上图所示:因为新添加的按钮左边离第一个按钮最近的边界是它的右边.
所以我们必须清楚地指定按第一个按钮的左边界为基准.
只需要传给构造函数SWT.LEFT值给FromData对象的alignment成员:
data.left = new FormAttachment(button, 0, SWT.LEFT);
我们同样的方法设置新按钮的右边,完成任务.
data.right = new FormAttachment(button, 0, SWT.RIGHT);
完整的代码如下:
import org.eclipse.swt.widgets.*; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.SWT; public class FormLayoutFormAttachment { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); FormLayout layout = new FormLayout(); layout.marginHeight = 5; layout.marginWidth = 10; shell.setLayout(layout); Button button = new Button(shell, SWT.PUSH); button.setText("Button"); FormData data = new FormData(); data.height = 50; data.right = new FormAttachment(100, -50); data.left = new FormAttachment(0, 10); data.top = new FormAttachment(1, 4, 0); button.setLayoutData(data); Button button2 = new Button(shell, SWT.PUSH); button2.setText("Button 2"); data = new FormData(); button2.setLayoutData(data); data.bottom = new FormAttachment(100, 0); data.top = new FormAttachment(button, 5); data.left = new FormAttachment(button, 0, SWT.LEFT); data.right = new FormAttachment(button, 0, SWT.RIGHT); shell.pack(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); } }
下面写一个更加复杂的程序,代码如下:我就不多解释了,应该都看得懂,运行结果出来后,
无论怎么改变窗口的大小,所有按钮的位置都没有改变.
import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class TestFormLayout { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); FormLayout layout = new FormLayout(); layout.marginHeight = 5; layout.marginWidth = 10; shell.setLayout(layout); Button button = new Button(shell, SWT.PUSH); button.setText("Button"); FormData data = new FormData(); data.height = 50; data.right = new FormAttachment(100, -50); data.left = new FormAttachment(0, 10); data.top = new FormAttachment(1, 4, 0); button.setLayoutData(data); Button button2 = new Button(shell, SWT.PUSH); button2.setText("Button 2"); data = new FormData(); button2.setLayoutData(data); data.bottom = new FormAttachment(100, 0); data.top = new FormAttachment(button, 5); data.left = new FormAttachment(button, 0, SWT.LEFT); data.right = new FormAttachment(button, 0, SWT.RIGHT); shell.pack(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); } }
下面写一个更加复杂的程序,代码如下:
运行结果出来后,无论怎么改变窗口的大小,所有按钮的位置都没有改变.
import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class FormLayoutComplex { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); FormLayout layout = new FormLayout(); shell.setLayout(layout); Button one = new Button(shell, SWT.PUSH); one.setText("One"); FormData data = new FormData(); data.top = new FormAttachment(0, 5); data.left = new FormAttachment(0, 5); data.bottom = new FormAttachment(50, -5); data.right = new FormAttachment(50, -5); one.setLayoutData(data); Composite composite = new Composite(shell, SWT.NONE); GridLayout gridLayout = new GridLayout(); gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; composite.setLayout(gridLayout); Button two = new Button(composite, SWT.PUSH); two.setText("two"); GridData gridData = new GridData(GridData.FILL_BOTH); two.setLayoutData(gridData); Button three = new Button(composite, SWT.PUSH); three.setText("three"); gridData = new GridData(GridData.FILL_BOTH); three.setLayoutData(gridData); Button four = new Button(composite, SWT.PUSH); four.setText("four"); gridData = new GridData(GridData.FILL_BOTH); four.setLayoutData(gridData); data = new FormData(); data.top = new FormAttachment(0, 5); data.left = new FormAttachment(one, 5); data.bottom = new FormAttachment(50, -5); data.right = new FormAttachment(100, -5); composite.setLayoutData(data); Button five = new Button(shell, SWT.PUSH); five.setText("five"); data = new FormData(); data.top = new FormAttachment(one, 5); data.left = new FormAttachment(0, 5); data.bottom = new FormAttachment(100, -5); data.right = new FormAttachment(100, -5); five.setLayoutData(data); shell.pack(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); } }