网站首页
JSP空间
动态资讯
开源项目
技术文档
资源下载
J2EE资源
客户论坛
在线支付
 
  技术文档>>JAVA>>新手入门>>基础入门>查看文档  
  组织swt/jface控件的利器:layout     
  文章作者:未知  文章来源:水木森林  
  查看:80次  录入:管理员--2007-11-17  
 
  在可视化编程时代,大多数可视化的gui开发工具都提供了按一定规则排列form中的控件的功能。但是对于java来说,支持可视化开发的工具并不多,虽然有一些这样的工具,但它们大多是第三方的产品,稳定性方面有一些欠缺。因此,在很多时候使用java编写gui程序时,就要使用布局(layout)来控制form上的控件的位置。

  本文主要讨论如何使用swt中提供的布局来安排控件的位置,并通过实例来演示这一过程。在swt中提供了5种布局:filllayout, rowlayout, gridlayout, formlayout, and stacklayout。下面我将详细讨论这5种布局的使用。

  filllayout

  filllayout是最简单的布局。它可以将控件横向或纵向进行排列,并且其中每个控件都有同样的宽度或高度。使用filllayout一般分为2步。

  1. 建立一个filllayout对象。

  2. 使用setlayout方法设置shell对象的布局。

  下面代码使用filllayout在shell上放了3个按钮,代码如下:

package layout;

import org.eclipse.swt.swt;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

public class testfilllayout
{
 public static void main(string[] args)
 {
  display display = new display();
  shell shell = new shell(display, swt.dialog_trim);
  shell.settext("filllayout演示");
  shell.setsize(400, 300);

  // 设置shell的布局
  filllayout layout = new filllayout();
  shell.setlayout(layout);

  // 向shell添加控件
  button button1 = new button(shell, swt.push);
  button1.settext("按钮1");

  button button2 = new button(shell, swt.push);
  button2.settext("按钮2");

  button button3 = new button(shell, swt.push);
  button3.settext("按钮3");

  shell.open();
  while (!shell.isdisposed())
  {
   if (!display.readanddispatch())
   {
    display.sleep();
   }
  }
  display.dispose();
 }
}

  界面如图1所示。

组织swt/jface控件的利器:layout(图一)
图 1 使用横向filllayout的shell界面

  如果想要shell上的控件纵向排列,可以在建立布局时将type属性设置成swt.vertical。代码如下:

filllayout layout = new filllayout();
layout.type = swt.vertical;
shell.setlayout(layout);

  图2是控件纵向排列的效果图

组织swt/jface控件的利器:layout(图二)
图 2 使用纵向filllayout的shell界面

  filllayout的构造函数重载了2次。其中一个构造函数有一个参数,这个参数就是type。因此,我们也可以通过filllayout的构造函数对type赋值。

shell.setlayout(new filllayout(swt.vertical));
rowlayout

  rowlayout的功能和filllayout差不多。只是它和filllayout的最大区别是每个控件并不一定是一样大小。而且rowlayout是按行排列,这一点和filllayout是不同的。在一行排满后,就从下一行开始排列。和rowlayout配合使用的还有一个rowdata类。这个类可以设置每一个控件的大小。下面代码是一个使用rowlayout的小例子。

package layout;

import org.eclipse.swt.swt;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

public class testrowlayout
{
 public static void main(string[] args)
 {
  display display = new display();
  shell shell = new shell(display, swt.dialog_trim);
  shell.settext("rowlayout演示");
  shell.setsize(220, 200);

  // 将shell的布局设置成rowlayout
  rowlayout layout = new rowlayout(swt.horizontal);
  layout.spacing = 30;
  layout.marginleft = 30;
  layout.margintop = 30;
  shell.setlayout(layout);

  rowdata rowdata = new rowdata();
  rowdata.height = 50;
  rowdata.width = 100;

  // 向shell添加控件
  button button1 = new button(shell, swt.push);
  button1.settext("按钮1");
  button1.setlayoutdata(rowdata);

  button button2 = new button(shell, swt.push);
  button2.settext("按钮2");

  button button3 = new button(shell, swt.push);
  button3.settext("按钮3");

  shell.open();
  while (!shell.isdisposed())
  {
   if (!display.readanddispatch())
   {
    display.sleep();
   }
  }
  display.dispose();
 }
}

  图3是使用rowlayout的效果图

组织swt/jface控件的利器:layout(图三)
图3 rowlayout效果图

  可以在两个地方设置和rowlayout相关的数据,一个是rowdata,它可以设置控件的大小。另外一个就是rowlayout本身,它可以设置控件开始排列的起点坐标(marginleft和margintop)、以及控件之间的间距等信息(spacing)。在rowlayout中有个很重要的属性justify。这个属性默认是false。当它为true时,将自动调整行或整列的控件,使其尽量占满一行或一列。 gridlayout

  gridlayout是swt中最重要的布局。这个布局十分强大,它可以满足大多数的需要。而且它的网络可以通过composite对象进行嵌套。gridlayout有两个构造函数。一个是默认的构造函数public gridlayout()。另外一个需要两个函数public gridlayout(int numcolumns, boolean makecolumnsequalwidth)。其中numcolumns是这个网格的列数,而另外一个参数将使每一列等宽。下面的代码是一个完整的关于gridlayout的例子。

package layout;

import org.eclipse.swt.swt;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

public class testgridlayout
{
 public static void main(string[] args)
 {
  display display = new display();
  shell shell = new shell(display);
  shell.settext("gridlayout演示");
  gridlayout layout = new gridlayout();
  layout.numcolumns = 3;
  layout.makecolumnsequalwidth = true;
  shell.setlayout(layout);

  // 建立左上角的按钮
  griddata data = new griddata(griddata.fill_both);
  data.widthhint = 200; //按钮的初始宽度为200
  button one = new button(shell, swt.push);

  one.settext("按钮1");
  one.setlayoutdata(data);

  // 建立一个composite对象,并在上面放三个按钮
  composite composite = new composite(shell, swt.none);
  data = new griddata(griddata.fill_both);
  data.horizontalspan = 2; // composite的占两个cell

  composite.setlayoutdata(data);
  layout = new gridlayout();
  layout.numcolumns = 1;
  layout.marginheight = 15;
  layout.marginright = 150;
  composite.setlayout(layout);
 
  // 建立第二个按钮
  data = new griddata(griddata.fill_both);
  button two = new button(composite, swt.push);
  two.settext("按钮2");
  two.setlayoutdata(data);

  // 建立第三个按钮
  data = new griddata(griddata.horizontal_align_end);
  button three = new button(composite, swt.push);
  three.settext("按钮3");
  three.setlayoutdata(data);

  // 建立第四个按钮
  data = new griddata(griddata.horizontal_align_beginning);
  button four = new button(composite, swt.push);
  four.settext("按钮4");
  four.setlayoutdata(data);

  // 建立下面的一个长按钮
  data = new griddata();
  data.horizontalalignment = griddata.fill;
  data.grabexcesshorizontalspace = true;
  data.horizontalspan = 3;
  data.verticalspan = 2;
  data.heighthint = 150;
  button five = new button(shell, swt.push);
  five.settext("按钮5");
  five.setlayoutdata(data);
  
  shell.pack();
  shell.open();
  while (!shell.isdisposed())
  {
   if (!display.readanddispatch())
   {
    display.sleep();
   }
  }
  display.dispose();
 }
}

  上面的例子将网格设成3列,在第一行的第一列放置了第一个按钮。然后将一个composite对象放到第一行第二、三列(data.horizontalspan = 2),在这个对象上放到个按钮。最后在下面建立了第5个按钮。

  formlayout

  formlayout是swt中最复杂的布局。在这一部分我将详细讨论formlayout。这个布局虽然复杂,但它确可以对控件进行更多的控制。

  formlayout和其它的布局类似,也有一个formdata类用于设置布局信息。但我其它的布局不同的是formlayout使用另外一个类来控制控件的大小和位置,这个类是formattachment。控件的上、下、左、右分别要4个formattachment对象来控制。通过这些formattachment对象可以控制当前控件如何在它的父窗口中显示,以及和其它控件的相对位置。

  在formlayout中,描述位置的4个属性(left、top、right、bottom)都是一个formattachment对象。而并不是一个简单的值。在formattachment中比较常用的属性是numerator,这个属性描述控件的4个边距shell的边缘的距离。 按百分比放置控件

  可以通过formattachment的numerator属性设置百分比。下面的代码将一个按钮在它的父窗口的宽度的40%处放置按钮。当shell的尽寸改变后,按钮的位置也随之变化,但按钮的大小并不改变。

button button = new button(shell, swt.push);
button.settext("按钮");
formdata data = new formdata();
data.left = new formattachment(40);
button.setlayoutdata(data);

  但如果同时设置data的left和right属性又如何呢?如果是这样的话,那么这个按钮的尺寸就会改变。下面的例子将一个按钮放到水平方向中心的位置。我们可以将left的比例设计为40%,而right的比例设置60%。如果这样设置,无论窗体如何变化,这个按钮始终在水平方向的中心。这是一个简单的数学计算。如果一个按钮的左边在40%的位置,而右边在60%的位置,也就是说,按钮的右边距窗体的右边也是40%。这样可以算出,按钮的宽度占窗体的20%(哈哈,要想使用formlayout,可要有一定的数学基础啊!)。

button button = new button(shell, swt.push);
button.settext("按钮");
formdata data = new formdata();
data.left = new formattachment(40);
data.right = new formattachment(60);
button.setlayoutdata(data);

  不过在使用formattachment同时给left和right或top和bottom赋值时,不能将这两个比例设成一样的,要不就将按钮压扁了(按钮看不到了,宽或高为0)。如果想要按钮在中心位置,这两个比例的和必须是100。而且left(top)的比例要小于right(bottom)的比例。

  设置控件的偏移量

  swt之所以提供了布局,目的就是让你尽量少使用绝对坐标来设置控件。但在有时,我们又必须使用绝对坐标。如果是这样的话,你可以使用控件的setlocation来设置,也可以使用formattachment提供的偏移量去达到同样的效果。

formdata data = new formdata();
data.left = new formattachment(0, 20);
data.top = new formattachment(0, 40);
button.setlayoutdata(data);

  上面的代码相当于setlocation(20, 40),即将按钮设置的位置设置成(20, 40)。

  根据其它控件的调整位置

  一般在窗体上都有不只一个控件,这些控件之间都是有一定关系的,它们的位置也是相对的。因此,formlayout为我们提供了根据其它控件设置当控件位置的方法。如根据另外一个控件设置当前控件左边或右边的位置。

  下面的例子将根据一个按钮的位置设置另外一个按钮的位置。有两个按钮,第二个按钮根据第一个按钮的底边设置自己的位置。

button button1 = new button(shell, swt.push);
button1.settext("按钮1");
formdata data1 = new formdata();
data1.top = new formattachment(20);
data1.left = new formattachment(40);
data1.right = new formattachment(50);
button1.setlayoutdata(data1);
// 第二个按钮
button button2 = new button(shell, swt.push);
button2.settext("按钮2");
formdata data2 = new formdata();
data2.left = new formattachment(button1, 0, swt.center);
data2.top = new formattachment(button1);
button2.setlayoutdata(data2);

  上面的"按钮2"将根据"按钮1"将自己水平方向的位置设置成"按钮1"的中心位置。
stacklayout

  我们在最后一部分来讨论stacklayout,并不是因为stacklayout在这5种布局中最复杂,而是这个布局并不在org.eclipse.swt.layout中,而在org.eclipse.swt.custom中。从这个布局的名子可看出,它是将许多swt控件放到一个集合中,这些控件有同样的尺寸和位置。但只有在最上面的控件才能被显示。

  stacklayout只有一个空的构造函数,它只有一个属性topcontrol,这个属必确定了哪一个控件可以被显示。这个属性默认值是null,也就是说,如果不设置它,那将没有控件被显示在窗体上。但要注意的是,设置topcontrol并不会将stacklayout中控件删除。

package layout;

import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.custom.stacklayout;
import org.eclipse.swt.swt;

public class teststacklayout
{
 public static void main(string[] args)
 {
  display display = new display();
  shell shell = new shell(display);
  stacklayout layout = new stacklayout();
  shell.setlayout(layout);
  stacklayoutselectionadapter adapter = new stacklayoutselectionadapter(shell, layout);
  button one = new button(shell, swt.push);
  one.settext("按钮1");
  one.addselectionlistener(adapter);
  button two = new button(shell, swt.push);
  two.settext("按钮2");
  two.addselectionlistener(adapter);
  button three = new button(shell, swt.push);
  three.settext("按钮3");
  three.addselectionlistener(adapter);
  layout.topcontrol = one;
  shell.open();
  while (!shell.isdisposed())
  {
   if (!display.readanddispatch())
   {
    display.sleep();
   }
  }
  display.dispose();
 }
}

class stacklayoutselectionadapter extends selectionadapter
{
 shell shell;
 stacklayout layout;

 public stacklayoutselectionadapter(shell shell, stacklayout layout)
 {
  this.shell = shell;
  this.layout = layout;
 }

 public void widgetselected(selectionevent event)
 {
  control control = layout.topcontrol;
  control[] children = shell.getchildren();
  int i = 0;
  for (int n = children.length; i < n; i++)
  {
   control child = children[i];
   if (child == control)
   {
    break;
   }
  }
  ++i;
  if (i >= children.length)
   i = 0;
  layout.topcontrol = children[i];
  shell.layout();
 }
}

  上面这个例子在shell上有三个按钮,通过按最上面显示的按钮,这三个按钮循环交替显示。
 
 
上一篇: sun的新java脚本语言    下一篇: eclipse rcp:用于构建平台的平台
  相关文档
java起步,环境的配置 11-17
javascript+dom访问xml文件数据实例 11-17
java 5.0 多线程编程实践 11-16
用jbuilder2007开发扩展jsf标签的插件 11-17
java应用热遍全球 11-17
利用java reflection(反射)原理,在hibernate里面实现对单表、.. 11-17
用struts管理大型的复杂网站 11-16
try catch finally与return的执行顺序 11-17
使用uml编写java 设计模式例子 factorymethod pattern 11-17
java进阶:编写跨平台java程序注意事项 11-16
java中的类型转换与强制类型转换的实现 11-16
java mail api及其应用 —— 一个邮件列表服务器的实现 (一).. 11-17
使用jakarta commons pool处理对象池化 11-17
java初学问题实录 11-17
基础教程:java代码编写程序的基本规范 11-16
movefirst 方法 11-16
使用manual for urlrewritefilter美化适合google的url 11-17
用jbuilder7开发一个简单的j2ee 应用 11-16
用java自制手机联网游戏 11-17
java技巧:使用管道数据流传送数据 11-17
返回首页 | 关于我们 | J网章程 | JSP空间合租 | 客服中心 | 免责声明 | 常见问题 | 参观机房
本站主机空间代理至厦门市华众网络科技有限公司
《中华人民共和国增值电信业务经营许可证》
编号:闽B2-20050079
@2005-2008福建JSP技术网 版权所有 闽ICP备05000928号
技术电话:13616026886
邮箱:admin@fjjsp.com 站长QQ,点击这里给我发消息