首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

SWT/JFace 佈局管理器詳解:GridLayout 與 GridData 精細控制完全指南

     編輯:Java 相關知識

GridLayout 簡介

GridLayout 是 SWT 功能最強大、最常用的佈局管理器。它將容器劃分為網格(行×列),每個子元件佔據一或多個儲存格,支援跨行跨列、四向對齊、空間搶佔、固定/最小/建議尺寸、邊距間距等精細控制,適合複雜對話框、表單、響應式視窗。

GridLayout 核心屬性

屬性類型預設說明
numColumnsint1欄數(列數由元件數量自動決定)
makeColumnsEqualWidthbooleanfalsetrue=所有欄位寬度相同(以最寬者為準)
marginLeft/Right/Top/Bottomint5容器四邊留白
horizontalSpacingint5欄與欄之間間距
verticalSpacingint5列與列之間間距

建構子 new GridLayout(int numColumns, boolean makeColumnsEqualWidth) 可一次設定核心參數。

GridData:單一元件佈局數據

每個子元件可透過 setLayoutData(GridData) 指定在網格中的行為。GridData 提供豐富屬性:

屬性說明常用常數
horizontalAlignment水平對齊BEGINNING, CENTER, END, FILL
verticalAlignment垂直對齊BEGINNING, CENTER, END, FILL
horizontalIndent水平縮進 (像素),需配合 BEGINNINGint
horizontalSpan跨越欄數int (≥1)
verticalSpan跨越列數int (≥1)
grabExcessHorizontalSpace容器加寬時是否搶佔額外空間boolean
grabExcessVerticalSpace容器增高時是否搶佔額外空間boolean
widthHint建議寬度 (像素),若未設 grab/FILL 則生效int
heightHint建議高度 (像素)int
minimumWidth/Height最小尺寸限制int

建構子多載:new GridData()、new GridData(int hAlign)、new GridData(int hAlign, int vAlign, boolean grabH, boolean grabV)、new GridData(int hAlign, int vAlign, boolean grabH, boolean grabV, int hSpan, int vSpan)。

範例一:基本對齊與 Span


GridLayout gl = new GridLayout(2, true); // 2欄、等寬
shell.setLayout(gl);

Button b1 = new Button(shell, SWT.PUSH); b1.setText("button1");
b1.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));

List list = new List(shell, SWT.BORDER);
list.add("item 1"); list.add("item 2"); list.add("item 3");
list.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_CENTER));

Button b2 = new Button(shell, SWT.PUSH); b2.setText("button #2");
GridData gd = new GridData(GridData.VERTICAL_ALIGN_END);
gd.horizontalIndent = 5; b2.setLayoutData(gd);

Button b3 = new Button(shell, SWT.PUSH); b3.setText("3");
b3.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL)); // 垂直填滿

shell.pack(); shell.open();

觀察: 四個元件依序填入 2×2 網格。verticalAlignment 控制各元件在儲存格內的垂直位置;horizontalIndent 讓 b2 向右縮進 5px。

範例二:GrabExcessSpace 響應式佈局


GridLayout gl = new GridLayout(3, false);
shell.setLayout(gl);

Label label = new Label(shell, SWT.BORDER); label.setText("label");
GridData gd3 = new GridData(); gd3.widthHint=60; gd3.heightHint=20; label.setLayoutData(gd3);

Text text = new Text(shell, SWT.SINGLE | SWT.BORDER); text.setText("text");
GridData gd = new GridData();
gd.grabExcessHorizontalSpace = true; gd.grabExcessVerticalSpace = true;
gd.horizontalAlignment = GridData.FILL; gd.verticalAlignment = GridData.FILL;
text.setLayoutData(gd);

Button btn = new Button(shell, SWT.PUSH); btn.setText("button");
GridData gd2 = new GridData();
gd2.grabExcessHorizontalSpace = true; gd2.grabExcessVerticalSpace = true;
gd2.horizontalAlignment = GridData.FILL; gd2.verticalAlignment = GridData.FILL;
btn.setLayoutData(gd2);

shell.setSize(300, 80); shell.open();

效果: 拉大視窗時,Text 與 Button 平均瓜分額外空間(皆 grab=true、FILL);Label 保持固定 60×20。若僅 Text grab=true,Text 獨佔額外空間。

範例三:Span 跨行跨列


GridLayout gl = new GridLayout(2, true);
shell.setLayout(gl);

Button b1 = new Button(shell, SWT.PUSH); b1.setText("button1");
b1.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));

List list = new List(shell, SWT.BORDER); // 佔據 (row1, col1)
list.add("item 1"); list.add("item 2"); list.add("item 3");
list.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_CENTER));

Button b2 = new Button(shell, SWT.PUSH); b2.setText("button #2");
GridData gd = new GridData(GridData.VERTICAL_ALIGN_END);
gd.horizontalSpan = 2; gd.horizontalAlignment = GridData.FILL; // 橫跨 2 欄
b2.setLayoutData(gd);

Button b3 = new Button(shell, SWT.PUSH); b3.setText("3");
GridData gd2 = new GridData(GridData.VERTICAL_ALIGN_END);
gd2.verticalSpan = 3; // 縱跨 3 列
b3.setLayoutData(gd2);

shell.pack(); shell.open();

網格佈局圖:

[ b1        ] [ list      ]
[ b2 (span2) ] [ list      ]
[ b3 (vSpan3)] [ list      ]
[ b3         ] [           ]
[ b3         ] [           ]

範例四:完整表單佈局(書籍資料錄入)


shell.setText("Book Entry Demo");
GridLayout gl = new GridLayout(4, false);
gl.verticalSpacing = 8; shell.setLayout(gl);

// Title: 標籤 + 文字框跨 3 欄
new Label(shell, SWT.NONE).setText("Title: ");
Text title = new Text(shell, SWT.SINGLE | SWT.BORDER);
GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); gd.horizontalSpan = 3; title.setLayoutData(gd);

// Author: 標籤 + 文字框跨 3 欄
new Label(shell, SWT.NONE).setText("Author(s): ");
Text authors = new Text(shell, SWT.SINGLE | SWT.BORDER);
gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); gd.horizontalSpan = 3; authors.setLayoutData(gd);

// Cover: 標籤縱跨 3 列 + CLabel 縱跨 3 列、固定 100x100
new Label(shell, SWT.NONE).setText("Cover: ");
GridData gdL = new GridData(); gdL.verticalSpan = 3; new Label(shell, SWT.NONE).setLayoutData(gdL);

CLabel cover = new CLabel(shell, SWT.BORDER);
gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 1; gd.verticalSpan = 3;
gd.heightHint = 100; gd.widthHint = 100; cover.setLayoutData(gd);

// Pages / Publisher / Rating: 三欄標籤 + 三欄輸入
String[] labels = {"Pages", "Publisher", "Rating"};
for (String lb : labels) new Label(shell, SWT.NONE).setText(lb + ": ");
Text pages = new Text(shell, SWT.SINGLE | SWT.BORDER);
pages.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
Text pub = new Text(shell, SWT.SINGLE | SWT.BORDER);
pub.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
Combo rating = new Combo(shell, SWT.READ_ONLY);
rating.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
rating.add("5"); rating.add("4"); rating.add("3"); rating.add("2"); rating.add("1");

// Abstract: 標籤 + 多行文字框跨 3 欄、垂直搶佔空間
new Label(shell, SWT.NONE).setText("Abstract:");
Text abs = new Text(shell, SWT.WRAP | SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
gd.horizontalSpan = 3; gd.grabExcessVerticalSpace = true; abs.setLayoutData(gd);

// Enter 按鈕:跨 4 欄、靠右
Button enter = new Button(shell, SWT.PUSH); enter.setText("Enter");
gd = new GridData(); gd.horizontalSpan = 4; gd.horizontalAlignment = GridData.END; enter.setLayoutData(gd);

// 設定測試資料
title.setText("Professional Java Interfaces with SWT/JFace");
authors.setText("Jack Li Guojie"); pages.setText("500pp");
pub.setText("John Wiley & Sons");
cover.setBackground(new Image(display, "C:/eclipse32.gif"));
abs.setText("This book provides a comprehensive guide for\nyou to create Java user interfaces with SWT/JFace.");

shell.pack(); shell.open();

此範例展示實戰中常見的:標籤+輸入配對、跨欄輸入框、圖片區域固定尺寸跨列、多行文字區域垂直擴展、按鈕靠右對齊。

GridLayout 進階技巧

  1. 巢狀 GridLayout:複雜區域建立子 Composite,各自獨立 GridLayout,再以 GridData 放入父網格。
  2. 動態增減元件:呼叫 parent.layout(true) 重新計算;若尺寸需變更再 parent.pack()。
  3. 最小尺寸限制:GridData.minimumWidth/Height 防止元件被壓縮過小。
  4. 等寬欄位:makeColumnsEqualWidth=true 適合按鈕列、標籤欄;輸入框區域建議 false。
  5. 高 DPI 適配:尺寸提示建議使用對話框單位 (DLU) 或依字型度量計算,而非硬編碼像素。

常見錯誤與除錯

現象原因解決
元件重疊Span 計算錯誤導致儲存格衝突檢查 horizontalSpan/verticalSpan 總和不超過 numColumns/行數
元件不顯示未呼叫 setLayoutData 或 GridData 設定錯誤每個子元件必須 setLayoutData;檢查 grab/FILL 組合
空間分配不均多欄 grabExcessHorizontalSpace=true 但寬度提示不同統一 widthHint 或移除 hint 讓建議尺寸決定初始比例
垂直置中失效容器高度未撐開(無 grabExcessVerticalSpace)父容器或祖先需 grabExcessVerticalSpace=true 且 FILL

GridLayout vs 其他佈局選型指南

場景推薦佈局理由
單一元件填滿視窗FillLayout最簡單、零配置
工具列、按鈕群、簡單流式排列RowLayout支援換行、固定尺寸、邊距
表單、對話框、精細對齊、響應式GridLayout網格化、Span、Grab、四向對齊、最完整
極度精確像素級定位、重疊、動畫無佈局手動 setBounds,罕見需求

總結

GridLayout + GridData 是 SWT 佈局系統的核心與精華。掌握 numColumns、Span、Alignment、GrabExcessSpace、Hint/Minimum 五大維度,即可構建出專業級、響應式、可維護的複雜 UI。建議開發者熟練掌握 GridLayout,作為日常開發的首選佈局管理器。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved