技术开发 频道

Eclipse开发经典教程:SWT布局

自定义布局

在SWT中,用户可以通过setLayout设置组件的布局信息。布局对象会根据父组件的大小和子组件的布局信息计算出每个子组件的位置和大小,使整个布局空间符合用户的需求。下面将介绍如何创建自己的布局类,实现用户自定义的布局。

Layout类

在SWT中,所有的布局类都继承于Layout抽象类。Layout有两个抽象方法。
1. computeSize (Composite composite, int wHint, int hHint, boolean flushCache) 2. layout (Composite composite, boolean flushCache)

computeSize方法负责计算组件所有子组件所占的高度和宽度,并返回一个Point类型的变量(width,height)。layout方法负责计算子组件的大小和位置,并按计算出来的位置排列子组件。

创建自己的布局类

如果用户希望组件按自己的方式进行布局,可以创建自己的布局类,实现自己的布局。要实现自己的布局,用户要继承Layout类,并实现layout方法和computeSize方法。下面将实现一个简单的按列进行布局的布局类,在此布局中,所有的子组件将按一列显示,并且子组件的宽度相等,代码如例程4所示。

例程4 ColumnLayout.java

public class ColumnLayout extends Layout { public static final int MARGIN = 4; public static final int SPACING = 2; Point [] sizes; int maxWidth, totalHeight; protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) { Control children[] = composite.getChildren(); if (flushCache || sizes == null || sizes.length != children.length) { initialize(children); } int width = wHint, height = hHint; if (wHint == SWT.DEFAULT) width = maxWidth; if (hHint == SWT.DEFAULT) height = totalHeight; return new Point(width + 2 * MARGIN, height + 2 * MARGIN); } protected void layout(Composite composite, boolean flushCache) { Control children[] = composite.getChildren(); if (flushCache || sizes == null || sizes.length != children.length) { initialize(children); } Rectangle rect = composite.getClientArea(); int x = MARGIN, y = MARGIN; //计算最大宽度 int width = Math.max(rect.width - 2 * MARGIN, maxWidth); for (int i = 0; i < children.length; i++) { int height = sizes[i].y; //设置子组件的位置 children[i].setBounds(x, y, width, height); //计算当前组件的y轴的坐标 y += height + SPACING; } } void initialize(Control children[]) { maxWidth = 0; totalHeight = 0; sizes = new Point [children.length]; for (int i = 0; i < children.length; i++) { //计算子组件的大小 sizes[i] = children[i].computeSize(SWT.DEFAULT, SWT.DEFAULT, true); maxWidth = Math.max(maxWidth, sizes[i].x); totalHeight += sizes[i].y; } totalHeight += (children.length - 1) * SPACING; } }

在ColumnLayout类中,通过layout方法对子组件重新计算位置,并设置子组件的位置。为了验证ColumnLayout类,下面通过ColumnLayoutTest类测试ColumnLayout类的效果,代码如例程5所示。

例程5 ColumnLayoutTest.java

public class ColumnLayoutTest { static Shell shell; static Button button3; public static void main(String[] args) { Display display = new Display(); shell = new Shell(display); shell.setLayout(new ColumnLayout()); new Button(shell, SWT.PUSH).setText("B1"); new Button(shell, SWT.PUSH).setText("Very Wide Button 2"); (button3 = new Button(shell, SWT.PUSH)).setText("Button 3"); new Text(shell, SWT.NONE).setText("text"); Button grow = new Button(shell, SWT.PUSH); grow.setText("Grow Button 3"); // 添加选择组件监听器 grow.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { button3.setText("Extreemely Wide Button 3"); //组件大小改变后通知父组件进行重新布局 shell.layout(); shell.pack(); } }); Button shrink = new Button(shell, SWT.PUSH); shrink.setText("Shrink Button 3"); shrink.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { button3.setText("Button 3"); //组件大小改变后通知父组件进行重新布局 shell.layout(); shell.pack(); } }); shell.pack(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } } }

当选择“Grow Button 3”组件后,layout方法会根据子组件的最大宽度调整所有子组件的宽度,程序运行效果如图6所示。

             
原始大小                                           宽度改变后
图6 自己定义布局


本节通过实例介绍了几种常用的布局方式,读者可以通过这几种布局方式实现SWT中大多数的布局需求。另外还有一种常用的布局FormLayout,有兴趣读者可以自行研究,在这里不一一介绍。

如果有某些比较特殊的要求,读者可以尝试修改布局类,以适应相关的布局。读者应该掌握如何设置组件相应的布局信息,掌握如何使用几种方式进行布局,特别是GridLayout布局方式。在有特殊需要的时候要能够修改布局类以适应自己的要求。

0
相关文章