目次
Javaちょっとできるプログラマ。教育業界のエンジニアです。
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 を右クリックしてビルドパスに追加します。
ソースコードを swt.jar に添付
パッケージ・エクスプローラにおいて参照ライブラリー内の swt.jar を右クリックしてプロパティを開きます。Java ソースの添付を開き先程 lib にコピーした src.zip を参照して OK を押します。これで SWT クラスの Javadoc ドキュメントが利用できるようになりました。
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("別のウィンドウ名");
}
}
}
その他のサンプルコード
記事の執筆者にステッカーを贈る
有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。
さらに詳しく →Feedbacks
ログインするとコメントを投稿できます。
関連記事
- Spring Security フォームログインのサンプルコードSpring フレームワークによる Web アプリケーション開発で、ログイン処理を実装する際は Spring Security が便利です。ここでは特に Spring Boot で Web アプリケーションを開発する場合を対象とし、フォームによる ID/Password ログインを行うためのサンプルコードをまとめます。 公式ドキュメント [Spring Security チュートリアル](http...
- Java配列の宣言方法 (C/C++との違い)Javaの配列 Javaの配列宣言方法はC/C++と似ているようで若干異なる。 初期化しない場合 C/C++の int array[10]; はJavaでは int array[] = new int[10]; となる。同様にC/C++の int array[3][3]; はJavaでは int array[][] = new int[3][3]; となる。 初期化
- PlantUML による UML 図の描き方PlantUML はテキスト形式で表現されたシーケンス図やクラス図といった UML (Unified Modeling Language) 図の情報から画像を生成するためのツールです。簡単な使い方をまとめます。 インストール方法の選択 Atom や Eclipse のプラグインをインストールしてエディタから利用する方法、JAR をダウンロードして Java コマンドで実行する方法、Redmine ...
- Akka HTTP サンプルコード (Scala)Akka アクターを用いて実装された汎用 HTTP フレームワークです。Spray の後継です。コアモジュールである akka-http-core は 2016/2/17 に experimental が外れました。akka-http などのいくつかのサブモジュールは 2016/3/1 現在 experimental のままですが、基本的な
- Kestrel の使用例Kestrel は Message Queue (MQ) の実装のひとつです。一般に MQ はアプリケーション間やプロセス間、スレッド間で非同期に通信するために用いられます。メッセージの送信側は MQ に書き込めば受信側の応答を待たずに次の処理に非同期に進むことができます。Kestrel はわずか 2500 行程の Scala で実装されており JVM で動作します。MQ 自体はメモリ上に存在する...