月蓝蓝 发表于 2008-12-30 11:14:30

SWT中模拟AWT的BorderLayout

BorderLayout 是 JFrame 的默认布局类,相信大家都用过,SWT没有提供这个Java程序员非常熟悉的Layout类。我们怎们来自己定义一个呢?首先要稍微了解一下Layout的内部实现原理。

www.ad119.cn/bbs/attachments/basic/20081230/2008123011124145377801.jpg


   Layouts 是一个容器用来对其子成员布局的一个算法,符合 Strategy Design Pattern . 当 SWT 打开一个 Composite 时,会调用 Composite 里的 layout.computeSize() 计算 Composite 的大小,然后再调 用 layout.layout() 设置子成员的位置和大小 . 如果需要, layout 会调用子成员的 getLayoutData() 来获得单个子成员特别的属性。

computeSize() 和 layout() 是抽象类 Layout 的两个抽象方法。

   要定义一个新的 layout ,也就是要定义一个 Layout 的子类, 实现 computeSize 和 layout. 对 BorderLayout 来说,我们需要区分子控件是在哪个位置的 , 是 WEST 的,还是 EAST 的,还是 CENTER 的,这个属性通过 Control.setLayoutData() 方法保存的各个控件里。

废话少说了,先看源代码   

public   classBorderLayoutextendsLayout {
   privateControl north;
   privateControl south;
   privateControl east;
   privateControl west;
   privateControl center;

   protected   voidgetControls(Composite composite) {
      Control[] children=composite.getChildren();
         for( inti=   0 , n=children.length; i<n; i    ) {
            Control child=children;
            BorderData borderData=(BorderData) child.getLayoutData();
             if(borderData==BorderData.NORTH)
                north=child;
             else   if(borderData==BorderData.SOUTH)
                south=child;
             else   if(borderData==BorderData.EAST)
                east=child;
             else   if(borderData==BorderData.WEST)
                west=child;
             else
                center=child;
      }
    }
}

   
   
                  
Control的Layout Data可以用Control.setLayoutData()方法设定, 所以getControl()方法找着各个控件的相应位置。

   protectedPoint computeSize(Composite composite,intwHint,inthHint,
             booleanflushCache) {
      getControls(composite);
         intwidth=   0 , height=   0 ;

      width   =west==   null   ?   0: getSize(west, flushCache).x;
      width   =east==   null   ?   0: getSize(east, flushCache).x;
      width   =center==   null   ?   0: getSize(center, flushCache).x;

         if(north!=   null ) {
            Point pt=getSize(north, flushCache);
            width=Math.max(width, pt.x);
      }
         if(south!=   null ) {
            Point pt=getSize(south, flushCache);
            width=Math.max(width, pt.x);
      }

      height   =north==   null   ?   0: getSize(north, flushCache).y;
      height   =south==   null   ?   0: getSize(south, flushCache).y;

         intheightOther=center==   null   ?   0: getSize(center, flushCache).y;
         if(west!=   null ) {
            Point pt=getSize(west, flushCache);
            heightOther=Math.max(heightOther, pt.y);
      }
         if(east!=   null ) {
            Point pt=getSize(east, flushCache);
            heightOther=Math.max(heightOther, pt.y);
      }
      height   =heightOther;

         return   newPoint(Math.max(width, wHint), Math.max(height, hHint));
    }

computeSize计算Composite所需的大小。

   protected   voidlayout(Composite composite,booleanflushCache) {
      getControls(composite);
      Rectangle rect=composite.getClientArea();
         intleft=rect.x, right=rect.width, top=rect.y, bottom=rect.height;
         if(north!=   null ) {
            Point pt=getSize(north, flushCache);
            north.setBounds(left, top, rect.width, pt.y);
            top   =pt.y;
      }
         if(south!=   null ) {
            Point pt=getSize(south, flushCache);
            south.setBounds(left, rect.height-pt.y, rect.width, pt.y);
            bottom-=pt.y;
      }
         if(east!=   null ) {
            Point pt=getSize(east, flushCache);
            east.setBounds(rect.width-pt.x, top, pt.x, (bottom-top));
            right-=pt.x;
      }
         if(west!=   null ) {
            Point pt=getSize(west, flushCache);
            west.setBounds(left, top, pt.x, (bottom-top));
            left   =pt.x;
      }
         if(center!=   null ) {
            center.setBounds(left, top, (right-left), (bottom-top));
      }
    }

而layout方法让控件们各归其位。整个布局调用是回归的。
完整的代码borderlayout.rar    上一页
页: [1]
查看完整版本: SWT中模拟AWT的BorderLayout