Java SWT の初期設定およびサンプルコード
[履歴] [最終更新] (2016/02/25 01:04:21)
1
作品
345
技術情報
最近の投稿
ここは
趣味の電子工作を楽しむ人のための作品共有プラットフォーム

ハードウェア技術を作品にして投稿してみませんか?
新着作品

概要

Eclipse Foundation が管理保守している SWT (Standard Widget Toolkit) を用いると Java で GUI ツールが作成できます。簡単なサンプルコードを示します。

インストール手順

ダウンロード

SWT: The Standard Widget Toolkit にアクセスして Releases / Stable というリンクからお使いの OS のものを選択してダウンロードします。"more..." というリンクをクリックすると 64bit など詳細な選択ができます。

インストール

解凍すると以下のものが同封されていることが分かります。

  • about.html (ライセンスファイルなど)
  • about_files (ライセンスファイルなど)
  • src.zip (jar のもとになったソースコード)
  • swt-debug.jar (デバッグビルド jar)
  • swt.jar (リリースビルド jar)

Java プロジェクトの作成

Eclipse を起動して新規 Java プロジェクトを作成します。

SWT ファイルをプロジェクト内にコピー

プロジェクト内に lib フォルダを新規作成します。先程解凍した swt.jar (または swt-debug.jar) および src.zip を lib 内にコピーします。swt-debug.jar を利用すると SWT クラス内部でブレークポイントが利用できたりしますがファイルサイズが大きくなってしまいます。通常は SWT クラス内を直接触ることはないため swt.jar で問題になりません。

swt.jar をビルドパスに追加

パッケージ・エクスプローラにおいて swt.jar を右クリックしてビルドパスに追加します。

Uploaded Image

ソースコードを swt.jar に添付

パッケージ・エクスプローラにおいて参照ライブラリー内の swt.jar を右クリックしてプロパティを開きます。Java ソースの添付を開き先程 lib にコピーした src.zip を参照して OK を押します。これで SWT クラスの Javadoc ドキュメントが利用できるようになりました。

Uploaded Image

Java クラスファイルの作成

プロジェクト内を右クリックするなどして新規に Java クラスファイルを追加します。「パッケージ swt, 名前 Main, メソッド・スタブ public static void main (String[] args) にチェック」という設定で新規作成してみました。更に以下のように編集します。

src/swt/Main.java

package swt;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class Main {

    public static void main(String[] args) {

        Display display = new Display(); // アプリが OS に問い合わせる窓口
        Shell shell = new Shell(display); // ウィンドウを表現するクラス
        shell.setText("ウィンドウ名");
        shell.open();

        while(!shell.isDisposed()) { // 終了指令がない間は無限ループ
            if(!display.readAndDispatch()) {
                display.sleep(); // イベントが発生しない間はスリープ
            }
        }
        display.dispose(); // リソースの解放
    }
}

Eclipse 内で実行

「右クリック → 実行 → Java アプリケーション」または「Alt + Shift + x, j」によって実行できます (Scala プロジェクトなどの場合は「エクスプローラ内を右クリック」→「実行」→「Scala アプリケーション」)。二回目以降は履歴が残るため「実行ボタンを押す」または「Ctrl + F11」でも実行可能です。完全に停止させるためにはコンソールタブの四角形の停止ボタンを押します。

Eclipse 外で実行

「メニューバーのファイル」→「エクスポート」→「Java / 実行可能 JAR ファイル」→「次へ」と進み、以下のように設定して完了を押します。生成された swt-gui.jar をダブルクリックすると Java アプリケーションが起動できます。

  • 起動構成: Main - swt-gui
  • エクスポート: 成果物 jar を出力したい場所
  • ライブラリー処理: 生成される JAR に必須ライブラリーをパッケージ (上から二番目)

ライブラリー処理について (補足情報)

生成される JAR に必須ライブラリーを抽出 (上から一番目) では swt.jar の内容が一旦展開されて、自分の class と一緒に jar に再度同封されます。

$ jar tf swt-gui.jar
META-INF/MANIFEST.MF
swt/
swt/HelloWorld.class  ← 自分が作ったクラス
swt-awt-win32-4430.dll  ← Windows 実行時用ネイティブライブラリー
swt-gdip-win32-4430.dll
swt-webkit-win32-4430.dll
swt-wgl-win32-4430.dll
swt-win32-4430.dll
swt-xulrunner-win32-4430.dll
swt-xulrunner24-win32-4430.dll
external.xpt
org/
org/eclipse/
org/eclipse/swt/
org/eclipse/swt/SWT.class  ← SWT クラス
...
org/eclipse/swt/widgets/Widget.class
version.txt

生成される JAR に必須ライブラリーをパッケージ (上から二番目) では swt.jar は展開されずにそのまま同封されます。

$ jar tf swt-gui.jar
META-INF/MANIFEST.MF
org/
org/eclipse/
org/eclipse/jdt/
org/eclipse/jdt/internal/
org/eclipse/jdt/internal/jarinjarloader/
org/eclipse/jdt/internal/jarinjarloader/JIJConstants.class
org/eclipse/jdt/internal/jarinjarloader/JarRsrcLoader$ManifestInfo.class
org/eclipse/jdt/internal/jarinjarloader/JarRsrcLoader.class
org/eclipse/jdt/internal/jarinjarloader/RsrcURLConnection.class
org/eclipse/jdt/internal/jarinjarloader/RsrcURLStreamHandler.class
org/eclipse/jdt/internal/jarinjarloader/RsrcURLStreamHandlerFactory.class
swt/
swt/HelloWorld.class  ← 自分が作ったクラス
swt.jar  ← 展開されずにそのまま同封

生成される JAR の隣のサブフォルダーに必須ライブラリーをコピー (上から三番目) では swt.jar は同封されません。別のフォルダが作成されてそれを参照することで swt.jar を利用します。

$ jar tf swt-gui.jar
META-INF/MANIFEST.MF
swt/
swt/HelloWorld.class

$ ls swt-gui_lib/
swt.jar

$ jar xvf swt-gui.jar
$ cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Class-Path: . swt-gui_lib/swt.jar
Main-Class: swt.HelloWorld

サンプルコード

コントロールウィジェットの追加

ボタンやテキストはコントロールとよばれる種類のウィジェットです。親コンテナを指定して追加します。親コンテナの最上位は Shell です。

src/swt/Main.java

package swt;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class Main {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("MyJavaApp");

        // ↓今回追加した部分
        shell.setLayout(new RowLayout()); // レイアウト設定

        Button button = new Button(shell, SWT.NULL); // 親コンテナは shell
        button.setText("押してください");

        Text text = new Text(shell, SWT.BORDER); // BORDER スタイル
        // ビットフラグなので以下のように複数指定可能です:
        // Text text = new Text(shell, SWT.BORDER | SWT.V_SCROLL);

        // ↑今回追加した部分

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

イベントリスナーをコントロールウィジェットに登録

src/swt/Main.java

package swt;

import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class Main {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("MyJavaApp");
        shell.setLayout(new FillLayout());

        MySwtApp app = new MySwtApp();
        app.createWidget(shell);

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

src/swt/MySwtApp.java

package swt;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

public class MySwtApp {
    private Text text;
    private Button button;
    private Label label;

    public void createWidget(Composite parent) {
        Composite composite = new Composite(parent, SWT.NULL);
        composite.setLayout(new RowLayout(SWT.VERTICAL));
        text = new Text(composite, SWT.BORDER);
        button = new Button(composite, SWT.NULL);
        button.setText("押してください");

        label = new Label(composite, SWT.NULL);
        label.setLayoutData(new RowData(100, -1));

        button.addSelectionListener(new SelectionListener() { // イベントリスナーの登録
            public void widgetSelected(SelectionEvent e) {
                label.setText(text.getText());
            }
            public void widgetDefaultSelected(SelectionEvent e) {
            }
        });
    }
}

スレッドを起動して UI を操作

メインのスレッドで生成したスレッドからは SWT の仕様上の制約からウィジェットを直接操作しての情報変更や情報取得ができません。ビルドは通りますがランタイムエラーが発生します。asyncExec (非同期) または syncExec (同期) を使用して操作する必要があります。

src/swt/Main.java

package swt;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class Main {

    public static void main(String[] args) {

        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("ウィンドウ名");
        shell.open();

        MyThread thread = new MyThread(display, shell);
        thread.start();

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

src/swt/MyThread.java

package swt;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class MyThread extends Thread {
    Display display = null;
    Shell shell = null;

    MyThread(Display display, Shell shell) {
        this.display = display;
        this.shell = shell;
    }

    public void run() {
        display.asyncExec(new InnerThread()); // 非同期
        display.syncExec(new InnerThread()); // 同期
    }

    class InnerThread implements Runnable {
        public void run() {
            shell.setText("別のウィンドウ名");
        }
    }
}

その他のサンプルコード