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

SWT/JFace FormLayout 彈性佈局精通:相對定位與動態調整大小技巧

     編輯:Java 相關知識

FormLayout 核心概念

org.eclipse.swt.layout.FormLayout 是 SWT 中最強大、彈性最高的佈局管理器。它不依賴固定網格或流向,而是透過 FormAttachment 定義控件邊緣之間的「相對關係」:

  • 依附於父容器邊緣 (百分比或像素偏移)。
  • 依附於同層其他控件邊緣 (對齊、間距)。

每個子控件需設定 FormData 作為 LayoutData,包含 left, right, top, bottom 四個 FormAttachment。

範例一:基礎相對定位 - 按鈕置中對齊

Button1 固定在 (20%, 20%)。Button2 的左/上邊緣依附於 Button1 的中心點,實現「Button2 中心對齊 Button1 中心」。

package swt_jface.demo2;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class FormLayoutSample {
    Display display = new Display();
    Shell shell = new Shell(display);

    public FormLayoutSample() {
        shell.setLayout(new FormLayout());

        Button button1 = new Button(shell, SWT.PUSH);
        button1.setText("button1");
        FormData fd1 = new FormData();
        fd1.left = new FormAttachment(20);  // 父容器左邊 20%
        fd1.top = new FormAttachment(20);   // 父容器上邊 20%
        button1.setLayoutData(fd1);

        Button button2 = new Button(shell, SWT.PUSH);
        button2.setText("button number 2");
        FormData fd2 = new FormData();
        // 關鍵:依附於 button1,offset=0, alignment=SWT.CENTER
        fd2.left = new FormAttachment(button1, 0, SWT.CENTER);
        fd2.top = new FormAttachment(button1, 0, SWT.CENTER);
        button2.setLayoutData(fd2);

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

    public static void main(String[] args) {
        new FormLayoutSample();
    }
}

範例二:實戰響應式對話框 - Label 換行、List 填滿、按鈕靠右下

展示 FormLayout 處理動態調整大小的經典模式:

  1. Label:左右依附父容器 0% 和 100%,寬度隨視窗變化,啟用 SWT.WRAP 自動換行。
  2. List:上依附 Label,下依附按鈕區塊,左右填滿,中間彈性伸縮。
  3. 按鈕:靠右下對齊,Ok 在 Cancel 左側固定間距。
  4. Resize 監聽:動態更新 Label 的 FormData 寬度強制重新佈局。
package swt_jface.demo2;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

public class Main {
    public static void main(String[] args) {
        Display display = new Display();
        final Shell shell = new Shell(display);
        
        Label label = new Label(shell, SWT.WRAP);
        label.setText("This is a long text string that will wrap when the dialog is resized.");
        
        List list = new List(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
        list.setItems(new String[] { "Item 1", "Item2" });
        
        Button button1 = new Button(shell, SWT.PUSH);
        button1.setText("Ok");
        Button button2 = new Button(shell, SWT.PUSH);
        button2.setText("Cancel");

        final int insetX = 4, insetY = 4;
        FormLayout formLayout = new FormLayout();
        formLayout.marginWidth = insetX;
        formLayout.marginHeight = insetY;
        shell.setLayout(formLayout);

        // Label: 左右滿版,高度自適應
        Point lblSize = label.computeSize(SWT.DEFAULT, SWT.DEFAULT);
        final FormData labelData = new FormData(lblSize.x, SWT.DEFAULT);
        labelData.left = new FormAttachment(0, 0);
        labelData.right = new FormAttachment(100, 0);
        label.setLayoutData(labelData);

        // 監聽 Resize 更新 Label 寬度 (確保 Wrap 正確)
        shell.addListener(SWT.Resize, e -> {
            Rectangle rect = shell.getClientArea();
            labelData.width = rect.width - insetX * 2;
            shell.layout();
        });

        // Cancel: 右下角
        FormData btn2Data = new FormData();
        btn2Data.right = new FormAttachment(100, -insetX);
        btn2Data.bottom = new FormAttachment(100, 0);
        button2.setLayoutData(btn2Data);

        // Ok: Cancel 左側
        FormData btn1Data = new FormData();
        btn1Data.right = new FormAttachment(button2, -insetX);
        btn1Data.bottom = new FormAttachment(100, 0);
        button1.setLayoutData(btn1Data);

        // List: 填滿中間區域
        FormData listData = new FormData();
        listData.left = new FormAttachment(0, 0);
        listData.right = new FormAttachment(100, 0);
        listData.top = new FormAttachment(label, insetY);
        listData.bottom = new FormAttachment(button2, -insetY);
        list.setLayoutData(listData);

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

FormAttachment 詳細參數解析

new FormAttachment(control, offset, alignment)

參數說明
control依附目標:null 或百分比 (0-100) 代表父容器邊緣;Control 實例代表同層控件邊緣。
offset像素偏移量。正數:向右/向下;負數:向左/向上。
alignment (僅當 control 為 Control 時)SWT.LEFT (預設,依附目標左邊)、SWT.RIGHT (依附目標右邊)、SWT.CENTER (依附目標中心)、SWT.TOP, SWT.BOTTOM。

常見組合模式

  • 置中:left = new FormAttachment(50, -width/2) 或 left = new FormAttachment(other, 0, SWT.CENTER)。
  • 緊貼另一控件右側:left = new FormAttachment(other, 5, SWT.RIGHT) (間距 5px)。
  • 填滿區間:同時設定 left 依附 A 右側,right 依附 B 左側。

FormLayout 進階技巧與避坑指南

1. 最小尺寸與 computeSize

FormLayout 不會強制子控件最小尺寸。若內容過多導致控件擠壓,需在 FormData 建構子指定 width/height,或呼叫 control.computeSize(w, h) 取得建議尺寸。

2. 避免循環依附

A.left 依附 B.right,B.left 依附 A.right 會造成佈局死循環。設計時建立清晰的「錨點」層級 (如:按鈕錨定右下 -> List 錨定按鈕上方 -> Label 錨定 List 上方)。

3. 動態增減控件

新增控件後呼叫 parent.layout()。移除控件前需 control.dispose() 並清理其 FormData 參考 (若有被其他控件依附),最後 parent.layout()。

4. 效能考量

FormLayout 計算複雜度較高 (約束求解)。控件數量超過 50+ 且頻繁 Resize 時,可能感覺延遲。此時考慮簡化依附關係或改用 GridLayout。

總結

FormLayout 以「相對依附」機制提供極致彈性,是實現複雜響應式對話框、精確對齊介面的利器。掌握 FormAttachment(control, offset, alignment) 三參數語意,配合 Resize 事件微調關鍵控件尺寸,即可駕馭各種動態佈局需求。

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