Eclipse界面編寫實例(2)--理解佈局3

2.3 GridLayout

GridLayout可能是最常用的、功能最強大的標準佈局類了,當然它也最複雜。GridLayout把容器裏的組件擺放在一個格子裏,它有許多可設置的域,並且同RowLayout類似,組件可以有相應的佈局數據,稱作GridDataGridLayout的強大在於它可以通過GridData來設置每一個控件。

2.3.1 GridLayout的可設置域

numColumns

numColumns 域是GridLayout的最重要的域,並且通常是第一個需要設置的域。組件從左到右擺放在列裏,當numColumns + 1個組件添加到容器中時,將創建一個新行。默認只有一列。以下代碼創建了由GridLayout管理的含有5個具有不同寬度的按鈕的Shell,隨後的列表顯示了當numColumns設爲1,23時的效果。

   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邊距和間距域與RowLayout的類似,不同的是左邊距和右邊距統一成marginWidth,上邊距和下邊距統一成marginHeight。同樣可以分別設置horizontalSpacingverticalSpacingRowLayout中的間距根據它的type類型設置水平間距或者垂直間距)。

2.3.2 GridData對象的域

GridDataGridLayout對應的佈局數據,可以通過setLayoutData設置組件的佈局數據。例如,可以採用如下代碼設置按鈕的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的風格位:

   button1.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));

       實際上,爲了更方便還提供了一些風格位的組合,例如:

   button1.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

注意FILL_ 風格同時設置對齊方式和佔位方式。GridData的風格位只對布爾值和枚舉值有效,數字域需要直接設置。

(使用Swing者注意) 最後使用GridData時需要主要的是:不要重複使用GridData 對象。每一個由GridLayout容器管理的組件必須有單獨的GridData對象。如果組件的佈局數據爲空,則SWT會自動創建一個單獨的GridData對象。

HorizontalAlignment VerticalAlignment

       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 VerticalSpan

span域可以使控件跨越幾個格子,常常與FILL風格一起使用。以下代碼把Button 5擴展到了兩個格子:

  

GridData gridData = new GridData();

gridData.horizontalAlignment = GridData.FILL;

gridData.horizontalSpan = 2;

button5.setLayoutData(gridData);

如果要把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, ListCanvas這樣的重量級組件上,當它們所在的容器增大時,可以使它們自動增大。例如如果設置一個Text組件可以橫向擴展,那麼當用戶調整Shell的寬度時,Text組件會自動擴展填滿新的橫向空間,而同一行上的其他組件保持寬度不變。當然,當Shell變小時,設置了此屬性的組件也是首先收縮的。在可以調整容器大小的環境中,很容易的就能想到設置grabExcessSpace域。作爲例子,我們仍然採用前面Button 3垂直擴展兩個單元格的例子,如下:

         

如果我們調整窗口的大小,那麼只有窗口變大了:

         

現在設置Button 3可以橫向和縱向擴展,B1B4僅縱向填充(不擴展),重新調整之後,如圖:

         

這一次,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");

       在典型的應用程序窗口中,通常會設置至少一個組件可以擴展。如果有多於一個的組件可以擴展,那麼它們平均分配擴展的空間,如圖所示:

           

       最後需要注意的是,如果一個組件可以橫向擴展,並且它的父容器變寬了,那麼組件所在的整列都變寬了。同樣如果組件可以縱向擴展,並且其父容器變高了,那麼組件所在的整行都變高了。這樣如果相應的行或列裏有其它的組件設置了填充(fill)屬性,那麼這些組件也會被拉伸。具有左對齊、居中對齊、右對齊的組件不會被拉伸,它們仍然在所在的行或列裏左對齊、居中對齊或右對齊。

WidthHint HeightHint

       widthHintheightHint域指示了希望組件可以具有的寬度和高度,前提是不與GridLayout其他要求約束矛盾。參見前面五個按鈕、三列的例子,假設要設置Button 570像素、高40像素,代碼如下:

       GridData gridData = new GridData();

       gridData.widthHint = 70;

       gridData.heightHint = 40;

       button5.setLayoutData(gridData);

       Button 5自然尺寸如左圖所示,右圖是70像素寬、 40像素高的圖示:

                

       注意,如果Button 5horizontalAlignment設置爲FILL,那麼GridLayout不能滿足其寬爲70像素的請求。

       最後一點,在一個平臺上表現好的設置,在另一個平臺上可能會有差別。由於不同平臺之間的字體大小和組件的自然大小不一樣,因此硬編碼像素值不是佈局窗體的最好方法。因而,除非萬不得已,儘量少用size hint


2.3.3 一個複雜的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後的效果:

           

       如果窗體尺寸變大,佈局重新調整爲如下所示:

           

       注意以下內容:

l         一共有37行;

l         dogPhoto Canvas可以變寬和變高,因爲它在橫向和縱向都設置了填充和擴展(本例沒有調整Image的大小,可以編程實現);

l         dogBreed Combo可以變寬,因爲設置了它橫向填充,並且和Canvas在相同的列裏;

l         dogName Text可以變寬,因爲設置了它橫向填充,並且它跨越的一列裏含有Canvas

l         ccategories List可以變高,因爲設置了它縱向填充,並且它跨越的行裏含有Canvas

l         因爲categories List變高了,它的垂直滾動條消失了(它沒有變寬);

l         ownerInfo Group變寬了,因爲設置了它橫向填充,且它跨越的一列裏含有Canvas

l         ownerInfo Group作爲Composite的子類,擁有自己的22列的GridLayout

l         ownerNameownerPhone Texts變寬了,因爲Group變寬了,並且在GroupGridLayout裏設置了它們橫向填充和擴展;

l         browsedelete 按鈕輕微交錯,由於設置了橫向填充,它們寬度保持一致;

l         delete Button在它所在的行上靠上對齊;

l         Categories標籤在categories List上居中對齊;

l         enter按鈕在它跨越的三列裏水平右對齊;

l         dogPhoto Canvas設置了寬度和高度初始值(width and height hints),因爲我們想儘可能的設置圖像大小爲80 x 80 像素;

l         categories List設置了高度初始值,爲List字體高度的12倍,因爲我們想讓列表初始顯示12行。

發佈了32 篇原創文章 · 獲贊 5 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章