`
D-tune
  • 浏览: 77559 次
  • 性别: Icon_minigender_1
  • 来自: 上海浦东
文章分类
社区版块
存档分类
最新评论

理解SWT布局(1)

阅读更多
摘要 
     当你用SWT编写应用程序的时候,你可能需要用布局(layout)来给你的窗口设置特特定的外观。布局控制组合窗口组件(composite)中的子组件的位置和大小。布局类都是抽象类Layout的子类。这篇文章为你展示了如何使用标准布局,以及如何编写定制你自己的布局。
 
作者:Carolyn MacLeod, OTI
    2001年3月22日
 
修订:Shantha Ramachandran, OTI
    2002年5月2日 
 
翻译:Link
    2006年5月
 
--------------------------------------------------------------------------------
布局 
概述
    当你用标准小窗口工具箱(SWT)编写应用程序的时候,你可能需要用布局来为你的窗口定制特定的外观。布局控制组合窗口组件(composite)中的子组件的位置和大小。 布局类都是抽象类Layout的子类。SWT提供了很多标准的布局类,你可以编写定制的布局类。
 
    在SWT中,定位和尺寸缩放不能自动地发生。应用程序可以初始化地确定一个Composite的子组件的大小和位置,或者可以通过一个调整大小的监听器来实现。另一个选择是指定一个布局类来定位和缩放这些子组件。如果子组件没有给定的尺寸大小,它们将会具有零尺寸(zero size)并且是不可见的。
 
   下面的图中显示了一些讨论布局时通常使用的术语。Composite(在这个例子中,是一个TabFolder)有一个location,一个clientArea和一个trim。Composite的大小是clientArea的大小加上trim的大小。这个Composite有两个并排布置的子组件。布局(Layout)管理子组件的大小和位置。这个布局允许子组件之间的spacing,以及子组件和布局边缘之间的margin。布局的大小和Composite的clientArea的大小一样。 
        
    小窗口部件(widget)的首选大小是显示它的内容所需要的最小的大小。在这个composite的例子中,首选大小是包含所有它的子组件的最小的矩形。如果子组件已经被应用程序定位,composite会基于这些子组件的大小和位置计算它自己的首选大小。如果composite用布局类来定位它的子组件,它要求布局来计算clientArea的大小,然后加上trim来决定它的首选大小。
 
标准布局 
   在SWT库中的标准布局类是:
 
  · FillLayout – 在单行或者单列中放置相同大小的小窗口部件。
  · RowLayout – 在一行或者多行中放置小窗口部件,应用了fill,wrap和spacing等选项。
  · GridLayout – 在网格中放置小窗口部件。
  · FormLayout  * 2.0新特性*通过定义四边的“粘贴”位置来放置小窗口部件。
 
  为了使用这些标准布局,你必须导入SWT的布局包:
 
   import org.eclipse.swt.layout.*;
 
  布局是可插件化的。为了设置composite小窗口部件的布局,你可以使用composite小窗口部件的setLayout(Layout)方法。在接下来的代码中,一个Shell(Composite的子类)用RowLayout来定位它的子组件:
  
   Shell shell = new Shell(); 
   shell.setLayout(new RowLayout());
 
   一个布局类可能有一个对应的布局数据(layout data)类 – 包括了定制子组件的布局数据的Object的子类。习惯上,布局数据类通过取代布局类类名中的Layout为Data为标识。例如:标准布局类RowLayout具有布局数据类RowData。布局类GridLayout使用布局数据类GridData,而布局类FormLayout具有名称为FormData的布局数据类。一个窗口小部件的布局数据类的设置如下: 
 
   Button button = new Button(shell, SWT.PUSH);
   button.setLayoutData(new RowData(50, 40));
 
这个文档中的例子
  这个文档中绝大多数的快照是通过运行下面的示例代码的变更版本来得到的。我们将会改变布局的种类,使用的选项,或者是子组件的数目。
 
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
 
public class LayoutExample {
 
      public static void main(String[] args) {
            Display display = new Display();
            Shell shell = new Shell(display);
            // Create the layout.
            RowLayout layout = new RowLayout();
            // Optionally set layout fields.
            layout.wrap = true;
            // Set the layout into the composite.
            shell.setLayout(layout);
            // Create the children of the composite.
            new Button(shell, SWT.PUSH).setText("B1");
            new Button(shell, SWT.PUSH).setText("Wide Button 2");
            new Button(shell, SWT.PUSH).setText("Button 3");
            shell.pack();
            shell.open();
            while (!shell.isDisposed()) {
                  if (!display.readAndDispatch()) display.sleep();
            }
      }
}
    运行以上代码得到如下的结果:
 
      
 
    如果用户调整了shell的大小使得右边的Button 3没有足够的空间,RowLayout将Button 3换行放置到下一行,如下所示:
 
    
 
    我们将会看到,使用布局和调整大小有紧密的关系。因此,这个文档中大多数的例子展示了当Composite变大或者变小时将会发生什么,以举例说明布局是如何工作的。
 
FillLayout 
 
    FillLayout是最简单的布局类。它在单行或者单列中放置小窗口部件,强制它们为同一大小。开始,窗口小部件都和最高的容器小部件一样高,和最宽的窗口小部件一样宽。FillLayout不会换行,而且你不能定制空白(margin)和间隔(spacing)。当Composite只有一个子组件时FillLayout也能被使用。例如,如果一个Shell有一个Group子组件,FillLayout会使Group完全填充这个Shell。
 
   这里是示例代码相关的一部分。首先我们创建了一个FillLayout,然后(如果我们需要垂直的样式)我们设定它的type域为SWT.VERTICAL,并且把它设定到Composite(一个Shell)中。这个Shell有三个按扭子组件,B1,B2和B3。注意在FillLayout中,子组件总是有相同的大小,而且充满可用空间。
 
    FillLayout fillLayout = new FillLayout();
    llLayout.type = SWT.VERTICAL;
    shell.setLayout(fillLayout);
    new Button(shell, SWT.PUSH).setText("B1");
    new Button(shell, SWT.PUSH).setText("B2");
    new Button(shell, SWT.PUSH).setText("Button 3");
 
  下面的表格显示了水平和垂直样式的FillLayout,初始状态以及当父组件增大时的不同点

 
初始状态
缩放后
fillLayout.type = SWT.HORIZONTAL
(默认)
 
fillLayout.type = SWT.VERTICAL
 
RowLayout
    RowLayout比FillLayout的使用更为普遍,因为它能够换行(warp)和提供了可配置的空白(margin)和间隔(spacing)。RowLayout有很多可配置的域。而且,RowLayout中的每个小窗口部件的高度和宽度都可以通过使用setLayoutData设置小窗口部件的RowData对象来指定。
 
RowLayout的可配置域

Type
* 2.0新特性*  
    type域控制RowLayout在水平行中还是在垂直列中放置小窗口部件。默认情况下RowLayout是水平方式的。
 
Wrap
    warp域控制RowLayout当前行中没有足够的空间时是否把小窗口部件换行放放置到下一行。默认情况下RowLayout是换行的方式.
 
pack
      如果pack为true,RowLayout中的小窗口部件会采用它们正常的大小,而且它们会尽可能的左对齐。如果pack为false,小窗口部件会填充可用的空间,就象FillLayout中的小窗口部件一样。默认情况下RowLayout的pack为false。
 
justify
     如果justify域为true,RowLayout中的小窗口部件从左到右在可用的空间中伸展开。如果父Composite变大,额外的空间均匀的分布在小窗口部件之中。如果packjustify都为true,窗口小部件采用它们正常的大小,而且额外的空间被放置在这些小窗口部件之间以保持它们完全的散开(justify)。默认情况下RowLayout不进行散开。
 
MarginLeft, MarginTop, MarginRight, MarginBottom和Spacing
    这些域控制小窗口部件之间的象素数(spacing)以及小窗口部件和父Composite的边界之间的象素数(margin)。默认情况下RowLayout为空白(margin)和间隔(spacing)保留3个象素。空白和间隔在下面的图中展示: 
   
     
   RowLayout的例子
  下面的示例代码中创建了一个RowLayout,设置它的所有域为非默认的值,然后把它设定到一个Shell中。
     RowLayout rowLayout = new RowLayout();
      rowLayout.wrap = false;
      rowLayout.pack = false;
      rowLayout.justify = true;
      rowLayout.type = SWT.VERTICAL;
      rowLayout.marginLeft = 5;
      rowLayout.marginTop = 5;
      rowLayout.marginRight = 5;
      rowLayout.marginBottom = 5;
      rowLayout.spacing = 0;
      shell.setLayout(rowLayout);
 
   如果你仅使用默认的域值,你只需要一行代码:
 
     shell.setLayout(new RowLayout());  
 
  在下面的表格中,展示了设置指定的域的结果:
 

 
初始状态
缩放后
wrap = true
pack = true
justify = false
type = SWT.HORIZONTAL 
(默认)
 
 
  wrap = false
(没有足够的空间则进行修剪)
 
  
 pack = false
(所有的小窗口部件都有相同的大小)
 
 
justify = true
(小窗口部件在可用空间中伸展开来)
 
 
  
 
 type = SWT.VERTICAL
(窗口小部件被垂直地安排在一列中)
 
  
 

RowLayout一起使用RowData对象

      每由RowLaout控制的一个小窗口部件都能通过设置它的RowData对象指定它初始的宽度和高度。以下代码用RowData对象来改变一个Shell中按钮(Button)的初始大小。
   
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
public class RowDataExample  
   public static void main(String[] args) {
       Display display = new Display();
       Shell shell = new Shell(display);
       shell.setLayout(new RowLayout());
       Button button1 = new Button(shell, SWT.PUSH);
       button1.setText("Button 1");
       button1.setLayoutData(new RowData(50, 40));
       Button button2 = new Button(shell, SWT.PUSH);
       button2.setText("Button 2");
       button2.setLayoutData(new RowData(50, 30));
       Button button3 = new Button(shell, SWT.PUSH);
       button3.setText("Button 3");
       button3.setLayoutData(new RowData(50, 20));
       shell.pack();
       shell.open();
       while (!shell.isDisposed()) {
           if (!display.readAndDispatch()) display.sleep();
       }
   }
}
 
  这是你运行这些代码后看到的结果。 
       
 
GridLayout
    
     GridLayout可能是最有用最强大的标准布局,但它也是最为复杂的。在一个GridLayout中,一个Composite的小窗口部件子组件被放置在网格中。GridLayout有很多可配置的域,而且,和RowLayout一样,它所放置的小窗口部件可以有一个关联的布局数据对象,叫做GridData。GridLayout的强大在于它具有为GridLayout所控制的每一个小窗口部件配置GirdData的能力。

 
GridLayout的可配置域
 
NumColumns
  numColumns域是GridLayout中最重要的域,而且它通常也是应用程序会设定的第一个域。小窗口部件被从左到右放置在不同的列中,当有numColumns + 1个小窗口部件被加到Composite中时,一个新的行就会被创建。默认情况下只有1列。接下来的代码创建了一个有着五个不同宽度的按钮(Button)的Shell,并用GridLayout来管理。以下的表格显示了当numColumns被设为1,2或者3时网格的情况。
 
 Display display = new Display();
 Shell shell = new Shell(display);
 GridLayout gridLayout = new GridLayout();
 gridLayout.numColumns = 3;
 shell.setLayout(gridLayout);
 new Button(shell, SWT.PUSH).setText("B1");
 new Button(shell, SWT.PUSH).setText("Wide Button 2");
 new Button(shell, SWT.PUSH).setText("Button 3");
 new Button(shell, SWT.PUSH).setText("B4");
 new Button(shell, SWT.PUSH).setText("Button 5");
 shell.pack();
 shell.open();
 while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) display.sleep();
 } 
 
numColumns = 1
numColumns = 2
numColumns = 3
 
 
 

MakeColumnsEqualWidth
    makeColumnsEqualWidth域强制让列都具有相同的宽度。默认值为false。如果我们改变上面的代码让它具有相同宽度的3列,这就是我们将得到的(注意:在没有进一步说明的情况下,小窗口部件在列中都是左对齐的)。

     

MarginWidth, MarginHeight, HorizontalSpacing, 和VerticalSpacing
     GridLayout中的marginspacing域和RowLayout中的这些域是相同的。不同的地方在于左边和右边的空白(margin)被组合成marginWidth,而项部和底部的空白被组合成marginHeight。而且,在GridLayout中,你可以独立地指定horizontalSpacingverticalSpacing,然而在RowLayout中,spacing应用于水平或者垂直样式是取决于RowLayout的类型的。
 
GridData 对象域
   GridData是关联于GridLayout的布局数据对象。为了设置一个小窗口部件的GridData对象,你可以使用setLayoutData方法。例如:为了给一个按钮(Button)设定GridData,我们可以象下面这样做:
 
 Button button1 = new Button(shell, SWT.PUSH);
 button1.setText("B1");
 button1.setLayoutData(new GridData());
 
    当然,这段代码只是用所有它的域的默认值创建了一个GridData对象,这各没有完全设置布局数据是一样的。有两种创建带有某些已设置域的GridData对象的方法。第一种方法是直接对域进行赋值,象这样:
 
 GridData gridData = new GridData();
 gridData.horizontalAlignment = GridData.FILL;
 gridData.grabExcessHorizontalSpace = true;
 button1.setLayoutData(gridData);
 
 第二种方法是是利用一些有用的API - GridData定义的“类型位”(style bits)。
 
 button1.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL |    GridData.GRAB_HORIZONTAL));
 
   事实上,为了进一步的方便,还提供了一些常用的“类型位”的联合。
   button1.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 
   注意到FILL_这些方便的类型设置了填充式排列(fill alignment)和抡占式(grab)填充。GridData的“类型位”只能被布尔型或者枚举型域使用。数据域必须直接进行设置。
 
 (Swing程序员注意)在我们讲述它们的域之前关于GridData最后要注意的是:不要重用GridData对象。每一个Composite中被GridLayout管理的小窗口部件必须有一个唯一的GridData对象。如果在布局的时候一个GridLayout中的小窗口部件的布局数据为null,就会为它创建一个唯一的GridData对象。

HorizontalAlignment和VerticalAlignment
    Alignment域用于指定在一个网格单元中的哪个位置水平的和/或者垂直的放置一个小窗口部件。每一个alignment域可以有下列的其中的一个值:
  •     BEGINNING
  •     CENTER
  •     END
  •     FILL
  默认的horizontalAlignment值是BEGINNING(或者左对齐)。默认的verticalAlignment值是CENTER。
  让我们回到我们那个在三个列中有五个按钮的例子,我们会改变Button 5的horizontalAlignment值。
 
horizontalAlignment = GridData.BEGINNING
 
(默认)
 
 
 horizontalAlignment = GridData.CENTER
 
 
 
 
 
 
 horizontalAlignment = GridData.END
 
 
 
 
 
 
 horizontalAlignment = GridData.FILL
 
 
 
 
 

 
 
HorizontalIndent
  horizontalIndent域允许你通过指定一个特定数目的象素数来把一个小窗口部件右移。这个域典型的只在horizontalAlignment值为BEGINNING时有用。我们不能用一个“类型位”来设置缩进,所以我们象下面这样把我们的例子中的Button 5缩进4个象素:

 

GridData gridData = new GridData();
gridData.horizontalIndent = 4;
button5.setLayoutData(gridData);
 
HorizontalSpan and VerticalSpan
    Span域让小窗口部件占有多于一个网格单元的空间。它们通常和FILL排列(aligment)一起使用。我们象下面这样让我们例子中的的Button 5跨越最后两个网格单元:

   

GridData gridData = new GridData();
gridData.horizontalAlignment = GridData.FILL;
gridData.horizontalSpan = 2;
button5.setLayoutData(gridData);
 
  如果我们决定让我们的Wide Button 2跨越两个网格单元,我们可以以这样的方式结束:

 
 
GridData gridData = new GridData();
gridData.horizontalAlignment = GridData.FILL;
gridData.horizontalSpan = 2;
button2.setLayoutData(gridData);
 
  或者我们可以让Button 3垂直地跨越两个网格单元:

 
 
GridData gridData = new GridData();
gridData.verticalAlignment = GridData.FILL;
gridData.verticalSpan = 2;
button3.setLayoutData(gridData);
 
GrabExcessHorizontalSpace和GrabExcessVerticalSpace
    grabExcessHorizontalSpacegrabExcessVerticalSpace域典型的被较大的小窗口部件如Text,List或者Canvas使用,以允许当它们包含的Composite变大时它们也相应的增大。如果一个Text抢占(grab)了额外的水平空间并用用户缩放了Shell的宽度,那么这个Text会占有所有这些新的水平空间而同一行中的其他的小窗口部件会维持原来的宽度。当然,当Shell缩小时抢占了额外空间的小窗口部件也是最先收缩的。在缩放的上下文中总是考虑grabExcessSpace域是最容易的。作为一个简单的例子,我们重新使用前面Button 3垂直地跨越两个网格单元的例子。这是这个例子的又一次展现:

  
 
  如果我们缩放这个窗口,唯一发生的事情只是窗口变大了。

 
 
   现在,我们让Button 3抢占额外的水平和垂直的空间,并且让B1和B4垂直地填充(不使用抢占),然后我们再一次对窗口进行缩放:

  
  
 
    这一次,Button 3再两个方向上都增大了,而B4垂直的增大。其他的按钮维持原来的大小。因为Button 3是垂直地抢占的并且它跨越了两行,它所跨越的最后一行变高了。注意到B1并没有增大-虽然它是垂直填充的-因为它的行并没有增大。因为Button 3是水平地抢占的,它的列变宽了,并且因为它是水平的填充的,它的宽度变大了以填充这一列。这里是所有五个按钮的代码:
 
 Button button1 = new Button(shell, SWT.PUSH);
 button1.setText("B1");
 GridData gridData = new GridData();
 gridData.verticalAlignment = GridData.FILL;
 button1.setLayoutData(gridData);
 
 new Button(shell, SWT.PUSH).setText("Wide Button 2");
 
 Button button3 = new Button(shell, SWT.PUSH);
 button3.setText("Button 3");
 gridData = new GridData();
 gridData.verticalAlignment = GridData.FILL;
 gridData.verticalSpan = 2;
 gridData.grabExcessVerticalSpace = true;
 gridData.horizontalAlignment = GridData.FILL;
 gridData.grabExcessHorizontalSpace = true;
 button3.setLayoutData(gridData);
 
 Button button4 = new Button(shell, SWT.PUSH);
 button4.setText("B4");
 gridData = new GridData();
 gridData.verticalAlignment = GridData.FILL;
 button4.setLayoutData(gridData);
 
 new Button(shell, SWT.PUSH).setText("Button 5");
 
   在一个典型的应用程序窗口中,你通常需要有至少一个抢占的小窗口部件。如果多于一个窗口试图抢占同样的空间,那么这些额外的空间会被均匀的分配到这些抢占式的小窗口部件中:
   
      
 
    最后一个关于抢占需要注意的地方。如果一个小窗口部件抢占了额外的水平空间并且它的父Composite变宽了,那么包含这个小窗口部件的整个列都变宽了。如果一个小窗口部件抢占了额外的垂直空间并且它的父Composite变高了,那么包含这个小窗口的整个行都变高了。这其中的含义是说如果任何在同一受影响的列或者行中的小窗口部件有具有填充排列(fill alignment)的属性,那么它也会伸展。具有开始(beginning),居中(center) 或结束(end)的排列属性不会伸展-他们会维持在变宽的这一列或者变宽的这一行的开始,中间或者结束处。

WidthHint和HeightHint
 如果不和GridLayout的约束系统中的其他需求发生冲突,widthHintheightHint域指出了你要让一个小窗口部件具有的宽或者高的象素数。回到五个按钮,三列的例子,假如我们要Button 5有70个象素宽40个象素高。我们象下面这样编码:
 
  GridData gridData = new GridData();
  gridData.widthHint = 70;
  gridData.heightHint = 40;
  button5.setLayoutData(gridData);
 
    Button 5在窗口中正常的大小如下左图所示,而70个象素宽40个象素高的Button 5如下右图所示:
    
       
  
    注意到,虽然如此,如果Button 5的horizontalAlignment是FILL,那么GridLayout就不能满足70个象素宽的需求。
 
    使用宽度和高度hint的最后一个意见。在一个平台上看起来很好的事情不一定在另一个平台也看起来很好。跨平台的字体大小和正常小窗口部件大小间的变化意味着硬编码的象素值通常不是布局窗口的最好办法。因此,如果你要使用大小hint,也让它尽可能少地被使用。
 
 一个复杂的GridLayout的例子
    至到目前为止,为了展示各个域是如何工作的,GridLayout的例子都相当的简单。现在,我们把它们放在一起创建一个比较复杂的例子。我们由手画一个粗糙的我们将要创建的窗口的草图开始,用以决定例如网格将含有多少个列,一些小窗口部件是否需要被伸展等问题。
 
     
 
     然后,我们开始从图中编写这个例子。代码如下。注意到我们增加了一些逻辑使得这段代码更有趣,例如,Browse…打开一个文件对话框(FileDialog)来读入一张图片,Canvas在一个重绘监听器中显示这张图片,Delete删除这张图片,Enter打印当前的狗以及它的主人的信息。这个例子在一个单独的main函数中编码,这让我们集中于布局的代码编写而不用为编程风格而感到烦乱。
 
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
 
public class ComplexGridLayoutExample {
     static Display display;
     static Shell shell;
     static Text dogName;
     static Combo dogBreed;
     static Canvas dogPhoto;
     static Image dogImage;
     static List categories;
     static Text ownerName;
     static Text ownerPhone;
 
     public static void main(String[] args) {
         display = new Display();
         shell = new Shell(display);
         shell.setText("Dog Show Entry");
         GridLayout gridLayout = new GridLayout();
         gridLayout.numColumns = 3;
         shell.setLayout(gridLayout);
  
         new Label(shell, SWT.NONE).setText("Dog's Name:");
         dogName = new Text(shell, SWT.SINGLE | SWT.BORDER);
         GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
         gridData.horizontalSpan = 2;
         dogName.setLayoutData(gridData);
 
         new Label(shell, SWT.NONE).setText("Breed:");
         dogBreed = new Combo(shell, SWT.NONE);
         dogBreed.setItems(new String [] {"Collie", "Pitbull", "Poodle", "Scottie"});
         dogBreed.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
 
         Label label = new Label(shell, SWT.NONE);
         label.setText("Categories");
         label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER));
  
         new Label(shell, SWT.NONE).setText("Photo:");
         dogPhoto = new Canvas(shell, SWT.BORDER);
         gridData = new GridData(GridData.FILL_BOTH);
         gridData.widthHint = 80;
         gridData.heightHint = 80;
         gridData.verticalSpan = 3;
         dogPhoto.setLayoutData(gridData);
         dogPhoto.addPaintListener(new PaintListener() {
             public void paintControl(final PaintEvent event) {
                  if (dogImage != null) {
                       event.gc.drawImage(dogImage, 0, 0);
                  }
             }
        });
 
        categories = new List(shell, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
        categories.setItems(new String [] {
             "Best of Breed", "Prettiest Female", "Handsomest Male",
             "Best Dressed", "Fluffiest Ears", "Most Colors",
             "Best Performer", "Loudest Bark", "Best Behaved",
             "Prettiest Eyes", "Most Hair", "Longest Tail",
             "Cutest Trick"});
        gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
        gridData.verticalSpan = 4;
        int listHeight = categories.getItemHeight() * 12;
        Rectangle trim = categories.computeTrim(0, 0, 0, listHeight);
        gridData.heightHint = trim.height;
        categories.setLayoutData(gridData);
  
        Button browse = new Button(shell, SWT.PUSH);
        browse.setText("Browse...");
        gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        gridData.horizontalIndent = 5;
        browse.setLayoutData(gridData);
        browse.addSelectionListener(new SelectionAdapter() {
             public void widgetSelected(SelectionEvent event) {
                 String fileName = new FileDialog(shell).open();
                  if (fileName != null) {
                     dogImage = new Image(display, fileName);
                 }
            }
       });
  
      Button delete = new Button(shell, SWT.PUSH);
      delete.setText("Delete");
      gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL |                GridData.VERTICAL_ALIGN_BEGINNING);
     gridData.horizontalIndent = 5;
     delete.setLayoutData(gridData);
     delete.addSelectionListener(new SelectionAdapter() {
         public void widgetSelected(SelectionEvent event) {
              if (dogImage != null) {
                   dogImage.dispose();
                   dogImage = null;
                   dogPhoto.redraw();
              }
         }
     });
  
     Group ownerInfo = new Group(shell, SWT.NONE);
     ownerInfo.setText("Owner Info");
     gridLayout = new GridLayout();
     gridLayout.numColumns = 2;
     ownerInfo.setLayout(gridLayout);
     gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
     gridData.horizontalSpan = 2;
     ownerInfo.setLayoutData(gridData);
  
     new Label(ownerInfo, SWT.NONE).setText("Name:");
     ownerName = new Text(ownerInfo, SWT.SINGLE | SWT.BORDER);
     ownerName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  
     new Label(ownerInfo, SWT.NONE).setText("Phone:");
     ownerPhone = new Text(ownerInfo, SWT.SINGLE | SWT.BORDER);
     ownerPhone.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  
     Button enter = new Button(shell, SWT.PUSH);
     enter.setText("Enter");
     gridData = new GridData(GridData.HORIZONTAL_ALIGN_END);
     gridData.horizontalSpan = 3;
     enter.setLayoutData(gridData);
     enter.addSelectionListener(new SelectionAdapter() {
         public void widgetSelected(SelectionEvent event) {
              System.out.println("\nDog Name: " + dogName.getText());
              System.out.println("Dog Breed: " + dogBreed.getText());
              System.out.println("Owner Name: " + ownerName.getText());
              System.out.println("Owner Phone: " + ownerPhone.getText());
              System.out.println("Categories:");
              String cats[] = categories.getSelection();
              for (int i = 0; i < cats.length; i++) {
                   System.out.println("\t" + cats[i]);
              }
         }
     });
  
     shell.pack();
     shell.open();
     while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) display.sleep();
     }
     if (dogImage != null) {
         dogImage.dispose();
     }
   }
}
 
    这是当Mary Smith输入Fifi后窗口看起来的样子:
 
  
 
   如果窗口被放大,布局调整如下所示:
 
 
 
  注意下面这些问题:
  • 这里有3列7行。
  • dogPhoto这个Canvas会变宽和变高同,这是因为它是填充的并且水平地和垂直的抢占的(虽然我们本应该缩放图片,但我们没有对图片进行缩放)。
  •  dogBreed这个Combo会变宽,因为它是水平的填充的,并且它和Canvans在同一列。
  •  dogName这个Text会变宽,那是因为它是水平填充的,并且它所跨越的其中一列包含有Canvas。
  • Categories这个List会变高,这是因为它是垂直填充的,并且它和Canvas跨越了相同的行。
  • 因为categories这个List变高了,它的垂直滚动条消失了(它并没有变宽)。
  • ownerInfo这个Group会变宽,这是因为它是水平的填充的,并且它所跨越的其中一列包含有Canvas。
  • 作为Composite的子类,ownerInfo这个Group有它自己的2列2行的GridLayout。
  • ownerNameownerPhone这两个Text会变宽,这是因为Group会变宽,并且它们在Group的GridLayout中是填充的和水平抢占的。
  • browsedelete这两个Button会稍微的缩进,而且因为它们都是水平填充的,它们有相同的宽度。
  • delete这个Button在它的行的顶部垂直的对齐。
  • “Categories”这个Label在categories这个List的顶端居中。
  • enter这个Button是水平地对齐到它所跨越的3列的最右边。
  • dogPhoto这个Canvas用宽度和高度hint来创建,这是因为如果可能的话,我们要让Image有80象素×80象素的大小。
  • categories这个List用List的字体的12倍的高度hint值来创建,这是因为我们要让List在初始状态下显示十二个项。
 
 

 

分享到:
评论

相关推荐

    swt布局.doc

    SWT布局是开发Java应用程序时使用SWT(Standard Widget Toolkit)框架进行用户界面设计的关键部分。布局管理器决定了窗口组件(如按钮、文本框等)在容器(如Composite)内的排列方式和尺寸。本文将详细介绍SWT布局...

    SWT开发布局(讲解Eclipse的开发插件)

    【SWT布局详解:Eclipse开发插件使用】 在Java平台上,SWT(Standard Widget Toolkit)是一种用于构建图形用户界面(GUI)的库,它是Eclipse IDE中的核心组成部分。SWT提供了一系列的基础控件和布局管理器,使得...

    SWT插件中文教程SWT常用方法

    SWT(Standard Widget Toolkit)是Java编程环境中用于创建图形用户界面(GUI)的一种开源库,它是Eclipse项目的一部分...通过阅读这个中文教程,开发者能够深入理解SWT的工作原理,并能够熟练地运用到自己的项目中去。

    swt工具文档 swt工具文档

    SWT(Standard Widget Toolkit)是Java编程环境中一个用于创建图形用户界面(GUI)的开源库。它是Eclipse项目的一部分,旨在提供...通过深入理解SWT的组件、布局和事件处理机制,开发者可以构建出丰富多样的用户界面。

    swt高级密笈源码swt

    1. **SWT组件**:SWT提供了大量的组件,如按钮(Button)、文本框(Text)、列表(List)、表格(Table)、树形视图(Tree)、进度条(ProgressBar)等。理解每个组件的用法和属性设置,可以创建丰富的用户界面。 2...

    swt教程 有关SWT怎么应用

    两者的关系可以理解为JFace在SWT的基础上增加了一层抽象,使得开发更加便捷。 开发SWT程序的基本步骤包括: 1. **获取和设置SWT库**:在Eclipse的plugins目录下找到对应的SWT库文件,例如org.eclipse.swt.win32....

    swt - designer 学习实例

    这个"swt - designer 学习实例"压缩包显然包含了一系列关于如何使用SWT进行编程的示例,这对于学习和理解SWT的用法非常有帮助。SWT为Java开发者提供了与本机操作系统深度集成的用户界面组件,如按钮、文本框、列表等...

    swt layout

    以下是关于SWT布局管理器的详细解释: 1. **FillLayout**: - FillLayout是最简单的布局管理器之一,它将所有子组件以相同的大小填充到父组件中。子组件通常会以一行或一列的形式排列。 - FillLayout有两种风格:...

    swt2.rarswt2.rarswt2.rarswt2.rarswt2.rar

    通过解压并合并这些PDF文件,可以获得完整的SWT学习资料,深入理解SWT的工作原理和实践应用。对于希望提升Java GUI编程能力,特别是使用SWT进行桌面应用开发的开发者来说,这是一个非常有价值的资源。

    java swt自定义控件

    Java SWT(Standard Widget Toolkit)是Java平台上用于创建桌面应用程序的一个库,它提供了丰富的...通过理解控件的基本原理、绘图机制、事件处理和布局管理,我们可以创建出满足特定需求的、富有吸引力的界面元素。

    swt学SWT者必备的帮助文档

    总之,SWT是Java GUI开发的一个强大选择,通过这个详细的帮助文档,学习者可以深入理解SWT的各个方面,从而有效地利用它来创建高效、美观的桌面应用程序。无论你是初学者还是有经验的开发者,这份资料都将是你探索和...

    SWT编程开发学习资料

    通过阅读和运行这些代码,你可以直观地理解SWT的工作原理,并学会如何解决实际问题。 7. **Eclipse开发**:Eclipse作为SWT的主要使用者,其开发工具对SWT提供了很好的支持。学习如何在Eclipse环境中创建、调试和...

    java程序设计之swt教程

    1. 理解SWT的基本结构和组件,包括控件、容器和布局。 2. 学习如何创建和配置控件,以及如何响应用户事件。 3. 掌握布局管理器的使用,了解如何根据需求选择合适的布局。 4. 实践编写简单的SWT程序,如“Hello, ...

    SWT widgets基本教程

    为了更好地理解 SWT Widgets 的使用,可以创建一个简单的演示项目来实验各种组件。 - 创建一个新的 Eclipse 项目。 - 添加必要的 SWT 组件。 - 编写代码来展示不同的组件及其功能。 - 运行程序观察效果。 #### 7. ...

    IBM GUI库SWT教程

    本教程将深入探讨SWT库的使用方法和特性,帮助开发者更好地理解和应用这一强大的GUI工具。 ### SWT基础 1. **组件库**:SWT提供了丰富的组件,如按钮、文本框、列表、树视图、表格等,这些组件可以组合起来构建...

    SWT API 帮助文档 及源码

    通过阅读源码,开发者可以深入理解SWT的工作原理,学习如何与本地系统进行通信,以及如何优化GUI性能。源码中包含了对各个平台特定功能的实现,例如Windows、Linux和macOS等。 在压缩包中的 "swt.CHM" 文件,是帮助...

    SWT详细精解

    1. SWT基础: SWT是基于原生系统API的,这意味着它能够提供与操作系统一致的外观和感觉。SWT通过JNI(Java Native Interface)与操作系统进行交互,提供高性能和高效的GUI开发。SWT的核心类包括Shell(顶级窗口)、...

    swt design for eclipse 3.2

    1. **SWT组件**:SWT提供了一系列的基本组件,如按钮(Button)、文本框(Text)、列表(List)、表格(Table)、树形视图(Tree)等,开发者可以使用这些组件来构建复杂的用户界面。每个组件都有丰富的API供开发者...

    SWT可视化插件

    对于初学者,可以先从理解SWT的基本组件和布局管理开始,然后逐渐深入到事件处理、自定义控件以及与其他Eclipse服务的集成等方面。同时,Window Builder的使用技巧也非常重要,例如熟悉其各种编辑模式、快捷键和预览...

Global site tag (gtag.js) - Google Analytics