ドキュメント



JavaFX: 相互運用性

8 SWTとのJavaFX相互運用性

この記事では、JavaFX SceneグラフをStandard Widget Toolkit (SWT)アプリケーションに追加する方法、およびSWTコントロールとJavaFXコントロールを相互運用する方法について説明します。

はじめに

SWTアプリケーションの開発者であれば、オペレーティング・システムのネイティブ・コントロールを使用するSWTを、アニメーションなどの高度なGUI機能を使用するように、容易に構成できないことはご存知でしょう。JavaFXをSWTに統合することによって、SWTアプリケーションを容易に強化できます。必要なものは、javafx.embed.swtパッケージのFXCanvasクラスのみです。javafx.embed.swtパッケージは、JDK_Home/jre/lib/ディレクトリ内にあるjfxswt.jarに含まれています。FXCanvasは、SWTキャンバスの表示が可能な任意の場所で使用できる、標準のSWTキャンバスです。それほど単純なことです。

この記事では、図8-1に示すインタラクティブなSWTボタンとJavaFXボタンの作成方法について説明します。

図8-1 SWTボタン(左側)とJavaFXボタン(右側)

SWTおよびJavaFXボタンのスクリーンショット

図8-2図8-3に示すように、ユーザーがいずれかのボタンをクリックすると、もう一方のボタンに表示されるテキストが変化します。この例は、SWTコードとJavaFXコードが相互運用する仕組みを示しています。

図8-2 SWTボタンをクリックしたときに変化するJavaFXボタンのラベル

図8-2の説明が続きます
「図8-2 SWTボタンをクリックしたときに変化するJavaFXボタンのラベル」の説明

図8-3 JavaFXボタンをクリックしたときに変化するSWTボタンのラベル

図8-3の説明が続きます
「図8-3 JavaFXボタンをクリックしたときに変化するSWTボタンのラベル」の説明

SWTコンポーネントへのJavaFXコンテンツの追加

JavaFXでは、JavaFXクラスを作成および操作するJavaコードは、JavaFXユーザー・スレッド内で実行されます。SWTでは、SWTウィジェットを作成および操作するコードは、イベント・ループ・スレッド内で実行されます。JavaFXをSWTに埋め込むと、これら2つのスレッドは同一になります。つまり、一方のツールキットで定義したメソッドをもう一方のツールキットからコールするときの制約がなくなります。

例8-1は、図8-1に示したSWTボタンとJavaFXボタンを作成するためのコードを示しています。コード内に示すように、FXCanvasクラス内でsetScene()メソッドを使用して、JavaFXコンテンツをFXCanvas内に設定します。SWTが強制的に新しいJavaFXコンテンツに基づいてキャンバスのレイアウトを行うようにするには、まずJavaFXコンテンツのサイズを変更します。これを行うには、JavaFXコンテンツを含むJavaFXウィンドウを取得し、sizeToScene()をコールします。JavaFXをSWTに埋め込むと、FXCanvasの新しい推奨サイズが設定され、これによりSWTは、埋め込まれたJFXコンテンツのサイズを、他のSWTコントロールと同じ方法で変更できるようになります。

JavaFXは、シーン内に配置された階層的なシーン・グラフに従ってコンテンツを構築します。例8-1のコードは、図8-4に示すシーン・グラフを使用して、シーン内にJavaFXボタンを配置しています。このシーン・グラフの説明は、コード例のコメント内に記載されています。

図8-4 SWTアプリケーション内のJavaFX Sceneグラフ

図8-4の説明が続きます
「図8-4 SWTアプリケーション内のJavaFX Sceneグラフ」の説明

例8-1 プレーンSWTおよびJavaFXボタンのJavaコード

import javafx.embed.swt.FXCanvas;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.paint.Color;
 
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
 
public class TwoButtons {
 
    public static void main(String[] args) {
        final Display display = new Display();
        final Shell shell = new Shell(display);
        final RowLayout layout = new RowLayout();
        shell.setLayout(layout);
 
        /* Create the SWT button */
        final org.eclipse.swt.widgets.Button swtButton =
                new org.eclipse.swt.widgets.Button(shell, SWT.PUSH);
        swtButton.setText("SWT Button");
 
        /* Create an FXCanvas */
        final FXCanvas fxCanvas = new FXCanvas(shell, SWT.NONE) {
            
                @Override
                public Point computeSize(int wHint, int hHint, boolean changed) {
                getScene().getWindow().sizeToScene();
                int width = (int) getScene().getWidth();
                int height = (int) getScene().getHeight();
                return new Point(width, height);
            }
        };
        /* Create a JavaFX Group node */
        Group group = new Group();
        /* Create a JavaFX button */
        final Button jfxButton = new Button("JFX Button");
        /* Assign the CSS ID ipad-dark-grey */
        jfxButton.setId("ipad-dark-grey");
        /* Add the button as a child of the Group node */
        group.getChildren().add(jfxButton);
        /* Create the Scene instance and set the group node as root */
        Scene scene = new Scene(group, Color.rgb(
                shell.getBackground().getRed(),
                shell.getBackground().getGreen(),
                shell.getBackground().getBlue()));
        /* Attach an external stylesheet */
        scene.getStylesheets().add("twobuttons/Buttons.css");
        fxCanvas.setScene(scene);
 
        /* Add Listeners */
        swtButton.addListener(SWT.Selection, new Listener() {
 
            @Override
            public void handleEvent(Event event) {
                jfxButton.setText("JFX Button: Hello from SWT");
                shell.layout();
            }
        });
        jfxButton.setOnAction(new EventHandler<ActionEvent>() {
 
            @Override
            public void handle(ActionEvent event) {
                swtButton.setText("SWT Button: Hello from JFX");
                shell.layout();
            }
        });
 
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();
    }
}

ボタンのスタイルは、Jasper Pottsによって執筆された、次の場所にあるブログに基づいています。
http://fxexperience.com/2011/12/styling-fx-buttons-with-css/

IDEでのSWT-JavaFXアプリケーションの作成

IDEでSWT-JavaFXアプリケーションを作成するには、単に次のライブラリをプロジェクトに追加するだけです。

  • swt.jar。次の場所から入手できるSWTのzipダウンロードに含まれています。
    http://eclipse.org/swt

  • jfxswt.jarJDK_HOME/jre/libディレクトリ内にあります。

    • たとえば、WindowsのデフォルトJDKインストールにおけるフルパスは次のとおりです。
      C:\Program Files\Java\jdk1.8.0\jre\lib

注意:

環境に応じて、すべてのJARファイルを32ビットまたは64ビットに統一します。

SWT-JavaFXアプリケーションのパッケージ化

SWT-JavaFXアプリケーションのパッケージ化方法は、JavaFXがJDK (7u6以降)にバンドルされているか、別の場所にインストールされている(JDK 7u6より前のリリースの場合)かによって異なります。

JavaFXがJDKにバンドルされている場合のアプリケーションのパッケージ化

NetBeans IDE 7.2以上を使用している場合、「IDEでのSWT-JavaFXアプリケーションの作成」で説明したライブラリを追加すれば、アプリケーションをパッケージ化するための特別な処理は必要ありません。単に「消去してビルド」を実行すると、プロジェクトの/distディレクトリ内に、ダブルクリック可能なJARファイルが生成されます。

スタンドアロンのJavaFXインストールを使用したアプリケーションのパッケージ化

SWT-JavaFXアプリケーションをビルドするときに、JARファイルをJavaFXアプリケーションとしてパッケージ化し、そのアプリケーションが、起動時に、ユーザーのシステム上にあるスタンドアロンのJavaFXランタイムを検出できるようにする必要があります。SWTライブラリ(swt.jar)は、リソース(ターゲット・システムに応じて32ビットまたは64ビット)として含める必要があります。

アプリケーション・ファイル

NetBeansプロジェクト 

ウィンドウを閉じる

目次

JavaFX: 相互運用性

展開 | 縮小