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

SWT/JFace GridLayout 佈局管理器完整指南:從入門到進階實戰

     編輯:Java 相關知識

前言

在 SWT/JFace 桌面應用開發中,GridLayout 是功能最強大、最常用的佈局管理器。它將父容器劃分為網格,支援靈活的單元格合併、對齊、間距控制與動態調整。本文系統整理 GridLayout 核心屬性、GridData 進階配置,並提供四個完整範例涵蓋從基礎到複雜表單的實戰場景。

GridLayout 核心屬性

GridLayout 本身控制整體網格結構:

屬性類型說明預設值
numColumnsint欄位數(列數由元件數量自動決定)1
makeColumnsEqualWidthbooleantrue 時所有欄寬相等false
marginWidthint左右邊距(像素)5
marginHeightint上下邊距(像素)5
horizontalSpacingint元件水平間距5
verticalSpacingint元件垂直間距5
marginLeft/Right/Top/Bottomint四個方向獨立邊距(優先於 marginWidth/Height)0

GridData:元件級佈局控制核心

每個子元件透過 setLayoutData(GridData) 定義在網格中的行為:

屬性說明常用常數
horizontalAlignment水平對齊方式BEGINNING, CENTER, END, FILL
verticalAlignment垂直對齊方式同上
horizontalSpan橫向跨越欄數int (預設 1)
verticalSpan縱向跨越列數int (預設 1)
grabExcessHorizontalSpace容器寬度變化時,是否搶佔多餘水平空間boolean
grabExcessVerticalSpace容器高度變化時,是否搶佔多餘垂直空間boolean
widthHint / heightHint建議寬/高(像素),未設定其他屬性時生效int
horizontalIndent水平縮進(需配合 BEGINNING 對齊)int

建構函數快速配置

// 常用建構子
new GridData()                                    // 預設
new GridData(int horizontalAlignment)             // 僅水平對齊
new GridData(int hAlign, int vAlign, boolean grabH, boolean grabV) // 完整控制
new GridData(int hAlign, int vAlign, boolean grabH, boolean grabV, int hSpan, int vSpan) // 含跨越

實戰範例 1:基礎對齊示範

public class GridLayoutSample {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setLayout(new GridLayout(2, true)); // 2欄、等寬

        // Button 1: 頂端對齊
        Button b1 = new Button(shell, SWT.PUSH);
        b1.setText("button1");
        b1.setLayoutData(new GridData(SWT.DEFAULT, SWT.BEGINNING));

        // List: 置中
        List list = new List(shell, SWT.BORDER);
        list.add("item 1"); list.add("item 2"); list.add("item 3");
        list.setLayoutData(new GridData(SWT.DEFAULT, SWT.CENTER));

        // Button 2: 底端對齊 + 縮進
        Button b2 = new Button(shell, SWT.PUSH);
        b2.setText("button #2");
        GridData gd2 = new GridData(SWT.DEFAULT, SWT.END);
        gd2.horizontalIndent = 5;
        b2.setLayoutData(gd2);

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

        shell.pack(); shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) display.sleep();
        }
        display.dispose();
    }
}

實戰範例 2:搶佔空間與尺寸提示

public class GridLayoutSampleGrabSpace {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setLayout(new GridLayout(3, false));

        // Label: 固定尺寸
        Label label = new Label(shell, SWT.BORDER);
        label.setText("label");
        GridData ld = new GridData();
        ld.widthHint = 60; ld.heightHint = 20;
        label.setLayoutData(ld);

        // Text: 搶佔所有多餘空間,填滿
        Text text = new Text(shell, SWT.SINGLE | SWT.BORDER);
        text.setText("text");
        GridData td = new GridData(SWT.FILL, SWT.FILL, true, true);
        text.setLayoutData(td);

        // Button: 同樣搶佔填滿
        Button btn = new Button(shell, SWT.PUSH);
        btn.setText("button");
        GridData bd = new GridData(SWT.FILL, SWT.FILL, true, true);
        btn.setLayoutData(bd);

        shell.setSize(300, 80);
        shell.open();
        // ... 事件循環
    }
}

關鍵:grabExcessHorizontalSpace=true 配合 horizontalAlignment=FILL 才能讓元件隨視窗縮放。

實戰範例 3:跨越單元格

public class GridLayoutSampleSpan {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setLayout(new GridLayout(2, true));

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

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

        // Button 2: 橫向跨越 2 欄,填滿
        Button b2 = new Button(shell, SWT.PUSH);
        b2.setText("button #2");
        GridData gd2 = new GridData(SWT.FILL, SWT.END);
        gd2.horizontalSpan = 2;
        b2.setLayoutData(gd2);

        // Button 3: 縱向跨越 3 列
        Button b3 = new Button(shell, SWT.PUSH);
        b3.setText("3");
        GridData gd3 = new GridData(SWT.DEFAULT, SWT.END);
        gd3.verticalSpan = 3;
        b3.setLayoutData(gd3);

        shell.pack(); shell.open();
        // ...
    }
}

實戰範例 4:完整書籍資料表單(綜合應用)

public class BookEntryForm {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("Book Entry Demo");
        
        GridLayout layout = new GridLayout(4, false);
        layout.verticalSpacing = 8;
        shell.setLayout(layout);

        // Title: 橫跨 3 欄
        createLabel(shell, "Title: ");
        Text title = new Text(shell, SWT.SINGLE | SWT.BORDER);
        GridData gd = new GridData(SWT.FILL, SWT.DEFAULT);
        gd.horizontalSpan = 3; title.setLayoutData(gd);

        // Author: 橫跨 3 欄
        createLabel(shell, "Author(s): ");
        Text authors = new Text(shell, SWT.SINGLE | SWT.BORDER);
        gd = new GridData(SWT.FILL, SWT.DEFAULT);
        gd.horizontalSpan = 3; authors.setLayoutData(gd);

        // Cover: 縱跨 3 列
        createLabel(shell, "Cover: ");
        GridData coverLd = new GridData();
        coverLd.verticalSpan = 3; 
        new Label(shell, SWT.NONE).setLayoutData(coverLd);
        
        CLabel cover = new CLabel(shell, SWT.BORDER);
        gd = new GridData(SWT.FILL, SWT.FILL);
        gd.horizontalSpan = 1; gd.verticalSpan = 3;
        gd.widthHint = 100; gd.heightHint = 100;
        cover.setLayoutData(gd);

        // Pages, Publisher, Rating: 各佔 1 欄
        createLabel(shell, "Pages");
        Text pages = new Text(shell, SWT.SINGLE | SWT.BORDER);
        pages.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT));

        createLabel(shell, "Publisher");
        Text pub = new Text(shell, SWT.SINGLE | SWT.BORDER);
        pub.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT));

        createLabel(shell, "Rating");
        Combo rating = new Combo(shell, SWT.READ_ONLY);
        rating.setItems("5", "4", "3", "2", "1");
        rating.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT));

        // Abstract: 橫跨 3 欄 + 搶佔垂直空間
        createLabel(shell, "Abstract:");
        Text abs = new Text(shell, SWT.WRAP | SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
        gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        gd.horizontalSpan = 3; abs.setLayoutData(gd);

        // Enter Button: 橫跨 4 欄,靠右
        Button enter = new Button(shell, SWT.PUSH);
        enter.setText("Enter");
        gd = new GridData(SWT.END, SWT.DEFAULT);
        gd.horizontalSpan = 4; 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, "cover.jpg"));
        abs.setText("This book provides a comprehensive guide for\nyou to create Java user interfaces with SWT/JFace.");

        shell.pack(); shell.open();
        // ... 事件循環
    }

    private static Label createLabel(Composite parent, String text) {
        Label l = new Label(parent, SWT.NONE);
        l.setText(text);
        return l;
    }
}

進階技巧與最佳實踐

1. 動態增減元件

// 新增元件後必須呼叫
parent.layout(true);   // 重新佈局
parent.pack();         // 可選:調整父容器大小

2. 讓特定欄/列自適應內容

GridLayout layout = new GridLayout(3, false);
// 第 1 欄固定,第 2 欄自適應,第 3 欄固定
// 無直接 API,需結合 grabExcessHorizontalSpace 控制

3. 避免常見陷阱

  • 忘記 setLayoutData:元件將使用預設 GridData(無 grab、無 span)。
  • FILL 未配合 grab:設 horizontalAlignment=FILL 但 grabExcessHorizontalSpace=false,元件不會隨視窗放大。
  • span 衝突:同一單元格不能有兩個元件各自跨越覆蓋。
  • pack() vs setSize():pack() 依據佈局計算最佳尺寸;setSize() 強制指定,佈局管理器會在該尺寸內安排。

4. 效能優化

  • 大量元件時,考慮 setRedraw(false) 批次更新後再 setRedraw(true)。
  • 避免在 paint 事件中做複雜計算。

總結

GridLayout 配合 GridData 提供了極高的佈局自由度:

  • 結構定義:numColumns、makeColumnsEqualWidth、邊距/間距
  • 元件行為:對齊 (Alignment)、跨越 (Span)、空間搶佔 (Grab)、尺寸提示 (Hint)
  • 實戰核心:FILL + grab=true 實現響應式;Span 實現複雜表單;Indent 微調位置

掌握這些概念,即可輕鬆構建專業級的 SWT/JFace 桌面應用介面。

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