SWTメモ - レイアウト編

最終更新日:2005/01/12
ogwa567@oki.com

目次

  1. はじめに
  2. レイアウトを理解する近道
  3. レイアウト・マネージャ
  4. サンプル其の1 - ファイルパス選択
  5. サンプル其の2 - ダイアログボックス
  6. サンプル其の3 - リスト編集
  7. 注意事項
  8. jface(おまけ)

はじめに

Swingと同じくSWTにもレイアウト・マネージャがあります。用意されているレイアウト・マネージャはJavaのAWTのレイアウトに近いと言えば近いのですが、慣れるまではどのレイアウト・マネージャを使ってどうレイアウトすればよいのか悩むのではないでしょうか。

そこでいくつかの画面構成を例として挙げ、それらに対するレイアウト方法を例として紹介します。SWTのレイアウト・マネージャの詳細についてはレイアウトを理解する近道で紹介しているページで詳しく解説されているので、ここでは個々のレイアウトの詳細については省略します。試行錯誤の結果なので間違いもあると思いますが、少しでも参考になれば幸いです。SWTのバーションはEclipse3.0に付属するものを対象としています。

レイアウトを理解する近道

例を紹介する前に、SWTのレイアウトを理解するために有用な情報源を紹介します。どれも必見の内容ですのでご覧になることをお勧めします。

SWTアプリケーションでのレイアウト
SWTの5つのレイアウトについて詳細に解説されています(日本語)。このページの内容でかなりの部分が理解できるのではないでしょうか。
Understanding Layouts in SWT
EclipseのサイトにあるSWTレイアウトの解説(英語)。個々のレイアウトの詳細な解説があります。複雑な画面構成例に対するGridLayoutとFormLayoutでのレイアウト方法もあり参考になります。
SWT Example Launcher(EcilpseのPlugin)
Eclipse Downloadsから適当なダウンロードサイトを選択して、使用しているEclipseバージョン番号をクリックし、Example Plug-insからプラットフォームに合ったファイルをダウンロードして展開します。展開してできるフォルダ内のfeatures, pluginsフォルダをEclipseのフォルダにコピーすればOKです。コピー前にEclipseを立ち上げていたら終了してからコピーしましょう。
Eclipseを起動して、ウィンドウ>ビューの表示>その他を選択すると「SWT Examples」がツリーに追加されているので、SWT Layoutsを選択します。これで4つのレイアウトを操作できるビューが表示されるので色々触ってみると良いでしょう。
SWT LayoutsでなくSWT Example Launcherを選択するとSWTアプリケーションやWidgetのExampleが見られるのでこちらも参考になります。

レイアウト・マネージャ

SWTで用意されているレイアウト・マネージャは以下の5つです。

パッケージ名 クラス名 説明
org.eclipse.swt.layout FillLayout 水平または垂直方向に均等サイズでWidgetを配置する
org.eclipse.swt.layout RowLayout 複数の行または列でWidgetを配置する
org.eclipse.swt.layout GridLayout 格子状にWidgetを配置する。HTMLのTableに似たレイアウトを行うことができる。
org.eclipse.swt.layout FormLayout 他のWidgetとの相対位置によってWidgetを配置する。やや特殊なレイアウト。
org.eclipse.swt.custom StackLayout Widgetをスタック上に重ねて一つずつ表示するレイアウト。
java.awt.CardLayoutに似ている。

この中で使用頻度が最も高いのはGridLayoutではないでしょうか。HTMLのTableに似た感覚でレイアウトできるレイアウト・マネージャです。これから紹介するサンプルでもほとんどがGridLayoutを使っています。

サンプル其の1 - ファイルパス選択

画面構成

ファイルやディレクトリパスを入力するテキストフィールドと、ファイル/ディレクトリ選択ダイアログを開くボタンがセットになった、以下のような画面を考えます。ウィンドウサイズを変更すると、テキストフィールドのサイズがそれに合わせて変更され、ラベルやボタンはサイズが変更しない仕様とします。

レイアウト

まずどのレイアウト・マネージャを使うかですが、FillLayoutは各Widgetを均等サイズに設定するので上の画面構成には適用できません。FormLayoutでレイアウトすることはできますが、やや特殊ですのでここでも以降でも扱わないことにします。StackLayoutはJavaのAWTのCardLayoutに似たものですのでこれも除外します。

そうすると消去法でRowLayoutかGridLayoutのどちらかになります。ただ、RowLayoutではウィンドウサイズの変更でテキストフィールドのサイズも変更する方法が無いようですので(ここはちょっと自身の無いところですが・・・)、GridLayoutを使うことにします。

画面構成はWidgetが3つ横に並んでいるので、GridLayoutのカラム数を3にし、テキストフィールドを配置する二つ目のGridを水平方向に引き伸ばす設定にすれば良いでしょう。以下のようなイメージです。

GridLayoutの作成

GridLayoutを生成するには引数を2つ持つコンストラクタを呼び出すと良いでしょう。第1引数はカラム数(int), 第2引数は各Gridを均等サイズにするかどうかのフラグ(boolean)です。今回の例では各Gridのサイズは均等ではないので、falseを指定します。

GridLayout layout = new GridLayout(3, false);

引数の無いコンストラクタを使ってGridLayoutを生成することもできます。その場合はnumColumns属性でカラム数をセットし、makeColumnsEqualWidth属性で均等サイズにするかどうかをセットします。どちらも重要な属性ですので、コンストラクタに引数を与えた方が良いでしょう。

GridLayout layout = new GridLayout();
layout.numColumns = 3;
layout.makeColumnsEqualWidth = false;

テキストフィールドの引き伸ばし

まずはテキストフィールドを作成します。SWT.SINGLEは単一行を指す定数、SWT.BORDERはWidgetに枠を付けるための定数です。

Text text = new Text(group, SWT.SINGLE | SWT.BORDER);

次にテキストフィールドのサイズをウィンドウサイズに合わせて広げる必要があります。そのためにGridDataを使います。GridDataは各Grid毎のレイアウト情報を保持するオブジェクトで、このオブジェクトに対して設定を行います。

テキストフィールドを引き伸ばすために必要なことは、

この2つです。これをGridDataに設定するには、コンストラクタにこれら定数の和を取ったものを与えます。

GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);

GridDataではこの2つの和を指す定数(FILL_HORIZONTAL)が予め用意されているので、以下のようにすることができます。こちらを使った方が良いでしょう。

GridData data = new GridData(GridData.FILL_HORIZONTAL);

このようにしてGridDataを生成したら、後は個々のWidgetにGridDataを設定します。設定にはsetLayoutData()メソッドの引数にGridDataを渡します。つまり、水平方向に引き伸ばすテキストフィールドを作る場合は以下の2行で良いということですね。

Text text = new Text(group, SWT.SINGLE | SWT.BORDER);
text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

ソースコード

以下、上の画面イメージを実現したサンプルプログラムです。ShellにGroup(コンテナの一種)を貼り付け、GroupにGridLayoutを設定し、各Widgetを貼り付けています。

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class FileSelectionGroup implements Constants {
    private Shell shell;

    public FileSelectionGroup(Shell shell) {
        this.shell = shell;
        createGroup();
    }

    private void createGroup() {
        GridLayout layout = new GridLayout(3, false);
        Group group = new Group(shell, SWT.NONE);
        group.setText("ファイル選択");
        GridData data = new GridData(GridData.FILL_HORIZONTAL);
        group.setLayoutData(data);
        group.setLayout(layout);

        Label label = new Label(group, SWT.NONE);
        label.setText("ファイル");

        Text text = new Text(group, SWT.SINGLE | SWT.BORDER);
        text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        Button button = new Button(group, SWT.PUSH);
        button.setText("選択");
    }

    public static void main(String[] args) {
        Display display = Display.getDefault();
        Shell shell = new Shell();
        shell.setLayout(new GridLayout(1, false));
        FileSelectionGroup f = new FileSelectionGroup(shell);
        shell.pack();
        shell.open();
        while (!f.shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }
}

実行結果

実行すると以下のようにテキストフィールドがウィンドウサイズに合わせて変化してくれます。

サンプル其の2 - ダイアログボックス

画面構成

OK, キャンセルボタンを持つダイアログボックスを考えてみます。メインエリアと書かれた部分に各画面固有のWidgetを配置し、その他は全部使いまわすという再利用を前提としたダイアログです。

ちなみに、メインエリアにメッセージを表示するダイアログはSWTで予め用意されてます。org.eclipse.swt.widgets.MessageBoxがそうです。ただ、メッセージでなく任意のWidgetを貼り付けるクラスが無いようですので(jfaceにはあるんだろうか・・・)これを作っていきます。

レイアウト

レイアウトのポイントになるのはボタンの右寄せです。まず右寄せが可能なレイアウトを採用する必要があるのですが、右寄せができるレイアウトは、FormLayoutを除けばGridLayoutだけのようです。というわけでレイアウトをまたもやGridLayoutにします。

ただし、今回は2つのボタンを右寄せする必要があるので、GridLayoutを入れ子にする必要があります。以下のようにOK, キャンセルを配置するCompositeを一つ追加して、そのCompositeを右寄せするイメージです。

では詳細を見ていきましょう。

メインエリア(grid1-1)

一つ目のGridです。再利用可能なダイアログを作ることが目的ですので、ここにはCompositeを配置してWidgetを加えるための下地を作っておきます。加えて、ウィンドウサイズが変更した場合にこの領域のサイズが垂直水平の両方向に変更される必要がありますので、以下のようにGridData.FILL_BOTH(x, y方向に引き伸ばす)を指定してGridDataを生成してセットします。

body = new Composite(shell, SWT.NONE);
GridData bodyData = new GridData(GridData.FILL_BOTH);
body.setLayoutData(bodyData);

境界線(grid1-2)

二つ目のGridには境界線を配置します。大外のレイアウトをカラム数1のGridLayoutにした場合は、上の図のように2つ目のGridは2行目に配置されます。

SWTで境界線を作るには、Label生成時に線を表す定数を与えることによって行います。

Label line = new Label(c, SWT.SEPARATOR | SWT.HORIZONTAL);

SWT.SEPARATORが境界線を表し、SWT.HORIZONTALが水平方向を表します。垂直方向の境界線を作る場合はSWT.VERTICALを指定します。

更に境界線は水平方向に引き伸ばす必要があるので、GridData.HORIZONTAL_ALIGN_FILLを指定して(Gridの幅 == ウィンドウサイズなのでHORIZONTAL_ALIGN_FILLでOK)GridDataを生成します。

GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
line.setLayoutData(data);

ボタンの右寄せ

ボタン一つだけを右寄せするなら、ボタンを作ってGridData.HORIZONTAL_ALIGN_ENDを指定してGridDataを生成すればOKです。ですが、ボタン二つの場合はそうもいかないので、二つのボタンを貼り付けるCompositeを新たに生成してそのCompositeを右寄せします。

Composite bottom = createRightAlignmentComposite();
okBtn = new Button(bottom, SWT.PUSH);
okBtn.setText("OK");
canBtn = new Button(bottom, SWT.PUSH);
canBtn.setText("キャンセル");


private Composite createRightAlignmentComposite() {
    Composite c = new Composite(shell, SWT.NONE);
    GridLayout layout = new GridLayout(2, false);
    layout.horizontalSpacing = HORIZONTAL_SPACING;
    layout.marginWidth = MARGIN_WIDTH;
    layout.marginHeight = MARGIN_HEIGHT;
    c.setLayout(layout);
    GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END);
    c.setLayoutData(data);
    return c;
}

GridLayoutには各Gridの間隔やマージンを設定できます。詳細はSWTのAPIドキュメントを参照して下さい。

ソースコード

ちょっと長くなってしまいましたが、以下が作成したクラスのソースコードです。

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

/**
 * @author ogawa567
 */
public class DefaultWindow {
    public static final int BUTTON_WIDTH = 70;
    public static final int HORIZONTAL_SPACING = 3;
    public static final int MARGIN_WIDTH = 0;
    public static final int MARGIN_HEIGHT = 2;

    private Shell shell;
    private Composite body;
    /* OKボタン */
    private Button okBtn;
    /* キャンセルボタン */
    private Button canBtn;

    /**
     * OK, キャンセルボタンを持つダイアログを生成する
     * @param parent ダイアログの親になるShell
     * @param title タイトル
     * @param style シェルのスタイル。モーダルなダイアログの場合は、
     * SWT.DIALOG_TRIM | SWT.PRIMARY_MODALを指定する。
     * @param okListener OKボタンのリスナ
     */
    public DefaultWindow(Shell parent, String title, int style,
        SelectionListener okListener) {
        shell = new Shell(parent, style);
        createComponents(shell, title, okListener);
    }

    /**
     * OK, キャンセルボタンを持つルートウィンドウを生成する
     * @param display
     * @param title
     * @param okListener
     */
    public DefaultWindow(Display display, String title,
        SelectionListener okListener) {
        shell = new Shell(display);
        createComponents(shell, title, okListener);
    }

    private void createComponents(Shell shell, String title,
        SelectionListener okListener) {
        GridLayout layout = new GridLayout(1, false);
        shell.setLayout(layout);
        shell.setText(title);

        // Body Composite
        body = new Composite(shell, SWT.NONE);
        GridData bodyData = new GridData(GridData.FILL_BOTH);
        body.setLayoutData(bodyData);

        // 境界線
        createHorizotalLine(shell);

        // OK, キャンセルボタン
        Composite bottom = createRightAlignmentComposite();
        okBtn = new Button(bottom, SWT.PUSH);
        okBtn.setText("OK");
        canBtn = new Button(bottom, SWT.PUSH);
        canBtn.setText("キャンセル");
        okBtn.addSelectionListener(okListener);
        final Shell s = shell;
        canBtn.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent arg0) {
                s.dispose();
            }
        });
    }

    private Label createHorizotalLine(Composite c) {
        Label line = new Label(c, SWT.SEPARATOR | SWT.HORIZONTAL);
        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        line.setLayoutData(data);
        return line;
    }

    private Composite createRightAlignmentComposite() {
        Composite c = new Composite(shell, SWT.NONE);
        GridLayout layout = new GridLayout(2, false);
        layout.horizontalSpacing = HORIZONTAL_SPACING;
        layout.marginWidth = MARGIN_WIDTH;
        layout.marginHeight = MARGIN_HEIGHT;
        c.setLayout(layout);
        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END);
        c.setLayoutData(data);
        return c;
    }

    /**
     * Shellに貼り付けられたCompositeを取得する。
     * Compositeのレイアウトは未設定
     * @return body を戻します。
     */
    public Composite getBody() {
        return body;
    }

    /**
     * Shellを取得する。
     * Shellのレイアウトは、GridLayout(1, false);
     * @return shell を戻します。
     */
    public Shell getShell() {
        return shell;
    }

    /**
     * ウィンドウを開く(Shellに対するpack(), open()を行うユーティリティメソッド)
     */
    public void open() {
        shell.pack();
        shell.open();
    }

    public static void main(String[] args) {
        Display display = Display.getDefault();
        Shell s = new Shell(display);

        SelectionListener listener = new SelectionAdapter() {
            public void widgetSelected(SelectionEvent arg0) {
                System.out.println("ボタンクリック!");
            }
        };
        DefaultWindow window = new DefaultWindow(s, "テスト", SWT.SHELL_TRIM,
            listener);

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

    }

}

実行結果

上のプログラムを実行すると、メインエリアにWidgetを何も貼り付けていないので下の画面より小さなウィンドウが生成されますが、ウィンドウを広げると以下のように二つのボタンが右寄せで表示されます。

Gridの最小サイズ設定

其の1, 其の2を実行してみると、貼り付けたのサイズがちょっと小さいですね。これはボタンの適切なサイズを計算してそれにあわせて各Gridのサイズが決められているからです。でもこれではボタンが押しづらいので最低限の横幅は確保してほしいものです。この最低限のサイズを各Gridに設定できます。GridDataクラスのheightHintとwidthHint属性です。それぞれGridの高さの最小値と幅の最小値を指す変数で、この変数に直接値を代入すれば良いです。

heightHintとwidthHintにアクセスするコードを毎回書くのは面倒ですので、例えばボタンに最小サイズを設定するケースが多ければ、以下のようなユーティリティメソッドを作ると良いでしょう。

public static Button createButton(Composite c, int style,
    String name, int minWidth, GridData d) {
    Button b = new Button(c, style);
    b.setText(name);

    int w = b.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
    if (w < minWidth) {
        d.widthHint = minWidth;
    } else {
        d.widthHint = w;
    }
    b.setLayoutData(d);

    return b;
}

ボタン生成コードをこのメソッド呼び出しで置き換えると、以下のようにボタンのサイズを変更できます。この例ではGridの最小幅を70にしています。

サンプル其の3 - リスト編集

画面構成

Eclipseの設定画面によくある、リストとリストを操作するボタンから成る画面を作成します。OK, キャンセル, 境界線はサンプル其の2と構成が同じです。ということで、其の2で作ったDefaultWindowクラスをそのまま使い、ここではそのメインエリアについてのレイアウトだけを考えることにします。

レイアウト

メインエリアのレイアウトを以下のように考えてみました。今回もGridLayoutを使っています。GridLayoutではHTMLのテーブルのようにGridを結合したようなレイアウトを作ることができるので、それを使ってレイアウトしています。

Gridの結合

ラベルやリストを配置するGridでは、horizontalSpan属性やverticalSpan属性によって、1つのGridが複数のGridを占めるようにする必要があります。例えばラベルを配置するGrid(grid1)ではGridLayoutのカラム数が2なので、horizontalSpan属性を使って2つ分のGridを占めるようにします。

listLabel = new Label(body, SWT.NONE);
listLabel.setText("リストラベル");
GridData data = new GridData();
data.horizontalSpan = 2;
listLabel.setLayoutData(data);

リストを配置するGridでは垂直方向のGridを結合する必要があるので、こちらはverticalSpan属性を使います。ここで結合するGrid数は4にします。ボタン数が3なので3でも良さそうですが、そうするとgrid5の位置がずれてしまうので、一つ余分にGridを結合すると配置がうまくいきます。grid5の下の領域には何も追加する必要はありません。

リストの最小サイズ設定

リストの最小サイズを指定しないと、リストに何も要素が無いような場合にサイズがかなり小さくなっていまいます。そこでボタンの時と同じようにリストを配置するGridに最小サイズを設定します。

ここでGridの最小サイズを

にします。リストの10行分確保するためには1行分の高さを取得してそれを10倍したものをセットします。

filterList = new List(body, SWT.MULTI | SWT.BORDER);
GridData data = new GridData(GridData.FILL_BOTH);
data.verticalSpan = 4;
data.widthHint = 200;
data.heightHint = filterList.getItemHeight() * 10;
filterList.setLayoutData(data);

ソースコード

以下、ソースコードです。ボタン生成にUtilクラスを使っていますが、これは其の2で紹介したcreateButton()メソッドの定義を持つ自作のユーティリティクラスです。

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;

public class SrcFilterDialog implements Constants {
    /* 親Shell */
    private Shell parent;
    /* 自分自身のShell */
    private Shell shell;
    /* コンポーネントを貼り付けるComopsite */
    private Composite body;

    private Label listLabel = null;
    private List filterList = null;
    private Button newBtn = null;
    private Button editBtn = null;
    private Button removeBtn = null;
    private Label line = null;
    private Button okBtn = null;
    private Button canBtn = null;

    public SrcFilterDialog(Shell parent) {
        this.parent = parent;
        createShell();
    }

    private void createShell() {
        DefaultWindow dialog = new DefaultWindow(parent, "ソースファイルのフィルタリング",
            SWT.DIALOG_TRIM | SWT.PRIMARY_MODAL, new OKButtonAdaptor());
        shell = dialog.getShell();
        body = dialog.getBody();
        GridLayout layout = new GridLayout(2, false);
        body.setLayout(layout);

        // リストの説明用ラベル生成
        createListLabel();

        // 複数選択可能なリスト
        createList();

        // リスト編集用ボタン
        createListEditButtons();
    }

    private void createList() {
        filterList = new List(body, SWT.MULTI | SWT.BORDER);
        GridData data = new GridData(GridData.FILL_BOTH);
        data.verticalSpan = 4;
        data.widthHint = 200;
        data.heightHint = filterList.getItemHeight() * 10;
        filterList.setLayoutData(data);
    }

    private void createListEditButtons() {
        newBtn = Util.createButton(body, SWT.PUSH, "新規...", BUTTON_WIDTH,
            new GridData());
        editBtn = Util.createButton(body, SWT.PUSH, "編集...", BUTTON_WIDTH,
            new GridData());
        removeBtn = Util.createButton(body, SWT.PUSH, "除去", BUTTON_WIDTH,
            new GridData());
    }

    private void createListLabel() {
        listLabel = new Label(body, SWT.NONE);
        listLabel.setText("リストラベル");
        GridData data = new GridData();
        data.horizontalSpan = 2;
        listLabel.setLayoutData(data);
    }

    class OKButtonAdaptor extends SelectionAdapter {
        public void widgetSelected(SelectionEvent arg0) {
            shell.dispose();
        }
    }

    public void open() {
        shell.pack();
        shell.open();
    }

    public static void main(String[] args) {
        Display display = Display.getDefault();
        Shell shell = new Shell(display);
        shell.setLayout(new GridLayout());
        Composite c = new Composite(shell, SWT.NONE);
        c.setLayout(new GridLayout());
        SrcFilterDialog test = new SrcFilterDialog(shell);
        test.open();

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

注意事項

GridDataを使いまわさない
各Widgetに対して設定するGridDataは必ず毎回生成しましょう。使いまわすとうまく表示されなくなるようです。APIドキュメントにも使いまわすなと書いてあります。

jface(おまけ)

jfaceって何?

ここまで3つサンプルを紹介しましたが、簡単なレイアウトにも関わらずコード量が多いですね。其の2のようなSWTのWidgetを組み合わせた出来合いのWidgetがあると開発効率も上がるでしょう。

jfaceはSWTをベースとして、実際のGUI開発でよく使われる便利なWidget群を提供するUIツールキットです。jfaceを使うことで複雑なアプリケーションの開発が容易になります。

ファイルフィールドエディタ

例えばサンプル其の1でファイルパスを選択する画面をSWTで作りました。これをjfaceのWidgetを使うと以下のようにすることができます(厳密に同じではありません。あくまでサンプルです。)

import org.eclipse.jface.preference.FileFieldEditor;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;

public class FileSelectionGroup2 extends ApplicationWindow implements Constants {

    public FileSelectionGroup2() {
        super(null);
    }

    protected Control createContents(Composite parent) {
        Composite c = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout(1, false);
        c.setLayout(layout);
        FileFieldEditor editor = new FileFieldEditor("test.preference", "ファイルパス", c);
        editor.setChangeButtonText("選択...");
        return c;
    }

    public static void main(String[] args) {
        ApplicationWindow w = new FileSelectionGroup2();
        w.setBlockOnOpen(true);
        w.open();
        Display.getCurrent().dispose();
    }
}

org.eclipse.jface.preference.FileFieldEditorはラベル, テキストフィールド, ボタンを組み合わせたWidgetです。上では適当な使い方をしていますが、どうやらPreferenceStoreと組み合わせることで強力な使い方ができるようです。
例えばテキストフィールドに入力された値を保存して次回起動時に反映させる必要がある場合、SWTだけでは保存と読み込みの仕組みを自分で作る必要がありますが、FileFieldEditorを使うとプロパティファイルからへの保存, 読み込みの仕組みを持っているようです。実際とあるEclipseのプラグインのソースを見るとこういったクラスが使われていて短いコード量で多くの機能を持つ画面を構成していました。SWTで効率よくGUIを作っていくにはjfaceのツールキットを積極的に使っていくと良いのではないかと思います。

資料室へ戻る


Copyright (c) 2004 OKI Software Co., Ltd.