ドキュメント



JavaFX: 相互運用性

7 JavaFXアプリケーションへのSwingコンテンツの埋込み

この章では、SwingコンポーネントをJavaFXアプリケーションに埋め込む方法について説明します。スレッドの制限について説明し、HTMLコンテンツとともにJavaFXアプリケーションに埋め込まれたSwingボタン、およびSwingボタンとJavaFXボタン間の相互運用性を示す実用的なアプリケーションを提供します。

JavaFXコンテンツをSwingアプリケーションに埋め込む機能は、JavaFX 2.0リリースから提供されています。JavaFXとSwingの相互運用性を強化するためにJavaFX 8で導入される新しいクラスでは、逆方向の統合が提供され、開発者はこのクラスを使用して、SwingコンポーネントをJavaFXアプリケーションに埋め込むことができるようになります。

この記事のコードを実行するには、JDK 8をコンピュータにインストールします。

SwingNodeクラス

JavaFX 8で導入されるSwingNodeクラスは、javafx.embed.swingパッケージ内にあります。このクラスを使用すると、SwingコンテンツをJavaFXアプリケーションに埋め込むことができます。SwingNodeオブジェクトのコンテンツを指定するには、javax.swing.JComponentクラスのインスタンスを受け入れるsetContentメソッドをコールします。setContentメソッドは、JavaFXアプリケーション・スレッドまたはイベント・ディスパッチ・スレッド(EDT)上でコールできます。ただし、スレッドに関するSwingの標準的な制限が適用されるため、Swingコンテンツにアクセスするには、コードをEDT上で実行するようにします。

例7-1のコードは、SwingNodeクラスの一般的な使用パターンを示しています。

例7-1

import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javax.swing.JButton;
import javax.swing.SwingUtilities;

public class SwingFx extends Application {

    @Override
    public void start (Stage stage) {
        final SwingNode swingNode = new SwingNode();

        createSwingContent(swingNode);

        StackPane pane = new StackPane();
        pane.getChildren().add(swingNode);

        stage.setTitle("Swing in JavaFX");
        stage.setScene(new Scene(pane, 250, 150));
        stage.show();
    }

    private void createSwingContent(final SwingNode swingNode) {
        SwingUtilities.invokeLater(() -> {
            swingNode.setContent(new JButton("Click me!"));
        });
    }
}

このコードを実行すると、例7-1に示す出力が生成されます。

図7-1 JavaFXアプリケーションに埋め込まれたSwing JButton

図7-1の説明が続きます
「図7-1 JavaFXアプリケーションに埋め込まれたSwing JButton」の説明

Swingコンテンツの埋込みとイベントの処理

SwingチュートリアルButtonHtmlDemoは、例7-2例7-3に示す3つのボタンに、フォント、色およびその他の書式設定を追加します。ボタンは、例7-5例7-6に示すように、マウスとキーボードのイベントに応答します。図7-2に、現在はJavaFXアプリケーション(SwingNodeSample)に埋め込まれたButtonHtmlDemo内のSwingを使用して作成された、3つのボタンを示します。SwingNodeSampleアプリケーションを作成し、すべてのイベントが適切なSwingボタンに配信され、処理されることを確認します。

図7-2 JavaFXアプリケーションに埋め込まれたButtonHtmlDemo

図7-2の説明が続きます
「図7-2 JavaFXアプリケーションに埋め込まれたButtonHtmlDemo」の説明

例7-2に示すように、左側および右側のボタンには、複数行のテキストがHTML書式設定を使用して実装されています。

例7-2

b1 = new JButton("<html><center><b><u>D</u>isable</b><br>"
                 + "<font color=#ffffdd>middle button</font>",
                 leftButtonIcon);

b3 = new JButton("<html><center><b><u>E</u>nable</b><br>"
                 + "<font color=#ffffdd>middle button</font>",
                 rightButtonIcon);

中央のボタンの単純な書式はHTMLを必要としないため、このボタンは例7-3に示すように、文字列ラベルとイメージで初期化されます。

例7-3

b2 = new JButton("middle button", middleButtonIcon);

例7-4に示すように、3つのボタンすべてに、ツールチップとニーモニック文字が含まれます。

例7-4

b1.setToolTipText("Click this button to disable the middle button.");
b2.setToolTipText("This middle button does nothing when you click it.");
b3.setToolTipText("Click this button to enable the middle button.");

b1.setMnemonic(KeyEvent.VK_D);
b2.setMnemonic(KeyEvent.VK_M);
b3.setMnemonic(KeyEvent.VK_E);

左側および右側のボタンは、それぞれ中央のボタンを無効および有効にするために使用します。アプリケーションで、これらのボタンに対するユーザー・アクションを検出してそれに応答するには、例7-5に示すように、アクション・リスナーをアタッチし、アクション・コマンドを設定します。

例7-5

b1.addActionListener(this);
b3.addActionListener(this);

b1.setActionCommand("disable");
b3.setActionCommand("enable");

例7-6に示すように、actionPerformedメソッドを実装します。このメソッドは、ユーザーが左側または右側のボタンをクリックするとコールされます。

例7-6

public void actionPerformed(ActionEvent e) {
    if ("disable".equals(e.getActionCommand())) {
        b2.setEnabled(false);
        b1.setEnabled(false);
        b3.setEnabled(true);
    } else {
        b2.setEnabled(true);
        b1.setEnabled(true);
        b3.setEnabled(false);
    }
}

ButtonHtmlDemo.javaクラスのコード全体を参照してください。

次に、JavaFXプロジェクトを設定し、SwingNodeSampleアプリケーションを実行します。

SwingNodeSampleアプリケーションを作成するには、次の手順を実行します。

JDK 8がコンピュータにインストールされていることを確認します。その後、次のようにNetBeans IDEでJavaFXプロジェクトを設定します。

  1. 「ファイル」メニューから、「新規プロジェクト」を選択します。

  2. 「JavaFX」アプリケーション・カテゴリで、「JavaFXアプリケーション」を選択し、「次」をクリックします。

  3. プロジェクトにSwingNodeSampleという名前を付け、JDK 8に基づくJavaFXプラットフォームを選択します。「終了」をクリックします。

  4. 「プロジェクト」ウィンドウで、「ソース・パッケージ」の下にあるswingnodesampleフォルダを右クリックします。「新規」を選択した後、「Javaクラス」を選択します。

  5. 新しいクラスにButtonHtmlという名前を付け、「終了」をクリックします。

  6. ButtonHtmlDemo.javaクラスのコードをコピーし、プロジェクト内に貼り付けます。

  7. ディスク上のswingnodesampleフォルダを開き、imagesフォルダを作成します。

  8. イメージleft.gifmiddle.gifおよびright.gifを右クリックし、イメージを別名で保存を選択してこれらのイメージをダウンロードし、imagesフォルダに保存します。

  9. SwingNodeSampleクラスで、NetBeansによって自動的に生成されたstartメソッド内のコードを削除します。

  10. かわりに、SwingNodeオブジェクトを作成し、例7-7に示すように、startメソッドを実装します。

    例7-7

    @Override
    public void start(Stage stage) {
        final SwingNode swingNode = new SwingNode();
        createSwingContent(swingNode);
        StackPane pane = new StackPane();
        pane.getChildren().add(swingNode);
    
        Scene scene = new Scene(pane, 450, 100);
        stage.setScene(scene);
        stage.setTitle("ButtonHtmlDemo Embedded in JavaFX");
        stage.show();
    }
    
  11. ButtonHtmlクラスによって生成された3つのボタンを埋め込むために、例7-8に示すように、SwingNodeオブジェクトのコンテンツがButtonHtmlクラスのインスタンスになるように設定します。

    例7-8

    private void createSwingContent(final SwingNode swingNode) {
        SwingUtilities.invokeLater(() -> {
            swingNode.setContent(new ButtonHtml());
        });
    }
    
  12. [Ctrl] (または[Cmd])キーと[Shift]キーを押しながら[I]キーを押して、import文を修正します。

SwingNodeSampleアプリケーションのソース・コードをダウンロードするには、「SwingNodeSample.zip」リンクをクリックします。

SwingNodeSampleプロジェクトを実行し、ボタンに対して提供される、あらゆる形の対話が想定どおりに動作することを確認します。

  • マウスをボタンの上に置き、ツールチップを表示します。

  • 左側および右側のボタンをクリックして、中央のボタンをそれぞれ無効および有効にします。

  • [Alt]キーを押しながら[D]キー、および[Alt]キーを押しながら[E]キーを押して、中央のボタンをそれぞれ無効および有効にします。

SwingコンポーネントとJavaFXコンポーネント間の相互運用性の追加

JavaFXボタンとSwingボタン間の相互運用性を提供できます。たとえば、図7-3に示すEnableFXButtonアプリケーションを使用すると、ユーザーはSwingボタンをクリックして、JavaFXボタンを無効または有効にできるようになります。逆に、図7-4に示すEnableButtonsアプリケーションを使用すると、ユーザーはJavaFXボタンをクリックして、Swingボタンをアクティブ化できるようになります。

図7-3 「Enable JavaFX Button」サンプル

図7-3の説明が続きます
「図7-3 「Enable JavaFX Button」サンプル」の説明

Swingボタンを使用したJavaFXボタンの操作

EnableFXButtonアプリケーションを作成するには、SwingNodeSampleアプリケーションを変更し、中央のボタンをjavafx.scene.control.Buttonクラスのインスタンスにします。変更済のアプリケーションでは、Swingボタン(「Disable FX」ボタンと「Enable FX」ボタン)は、JavaFXボタン(「FX」ボタン)を無効および有効にするために使用します。図7-3に、EnableFXButtonアプリケーションを示します。

EnableFXButtonアプリケーションを作成するには、次の手順を実行します。

  1. 「ファイル」メニューから、「新規プロジェクト」を選択します。

  2. 「JavaFX」アプリケーション・カテゴリで、「JavaFXアプリケーション」を選択し、「次」をクリックします。

  3. プロジェクトにEnableFXButtonという名前を付けます。

  4. 「プロジェクト」ウィンドウで、「ソース・パッケージ」の下にあるenablefxbuttonフォルダを右クリックします。「新規」を選択した後、「Javaクラス」を選択します。

  5. 新しいクラスにButtonHtmlという名前を付け、「終了」をクリックします。

  6. ButtonHtmlDemo.javaクラスのコードをコピーし、プロジェクト内に貼り付けます。

  7. パッケージ宣言をenablefxbuttonに変更します。

  8. ディスク上のenablefxbuttonフォルダを開き、imagesフォルダを作成します。

  9. イメージdown.gifmiddle.gifを右クリックし、イメージを別名で保存を選択してこれらのイメージをダウンロードし、imagesフォルダに保存します。

  10. EnableFXButtonクラスで、例7-9に示すように、Buttonオブジェクトを宣言します。

    例7-9

    public class EnableFXButton extends Application {
        public static Button fxbutton;
    
  11. NetBeans IDEによって自動的に生成されたstartメソッド内のコードを削除し、例7-10に示すように、startメソッドを実装します。

    例7-10

    @Override
    public void start(Stage stage) {
        final SwingNode swingNode = new SwingNode();
        createSwingContent(swingNode);
        BorderPane pane = new BorderPane();
        fxbutton = new Button("FX button");
        
        pane.setTop(swingNode);
        pane.setCenter(fxbutton);
    
        Scene scene = new Scene(pane, 300, 100);
        stage.setScene(scene);
        stage.setTitle("Enable JavaFX Button");
        stage.show();
    }
    
  12. 例7-11に示すように、SwingNodeクラスのimport文を追加します。

    例7-11

    import javafx.embed.swing.SwingNode;
    
  13. 例7-12に示すようにcreateSwingContentメソッドを実装して、SwingNodeオブジェクトのコンテンツを設定します。

    例7-12

    private void createSwingContent(final SwingNode swingNode) {
        SwingUtilities.invokeLater(() -> {
            swingNode.setContent(new ButtonHtml());
        });
    }
    
  14. [Ctrl] (または[Cmd])キーと[Shift]キーを押しながら[I]キーを押して、import文をjavax.swing.SwingUtilitiesクラスに追加します。

  15. fxbuttonの初期化を例7-13に示すコードで置換して、イメージを追加し、JavaFXボタンのツールチップとスタイルを設定します。

    例7-13

    Image fxButtonIcon = new Image(
    getClass().getResourceAsStream("images/middle.gif"));
    
    fxbutton = new Button("FX button", new ImageView(fxButtonIcon));
    fxbutton.setTooltip(
    new Tooltip("This middle button does nothing when you click it."));
    fxbutton.setStyle("-fx-font: 22 arial; -fx-base: #cce6ff;");
    
  16. [Ctrl] (または[Cmd])キーと[Shift]キーを押しながら[I]キーを押して、例7-14に示すインポート文を追加します。

    例7-14

    import javafx.scene.image.Image;
    import javafx.scene.image.ImageView;
    import javafx.scene.control.Tooltip;
    
  17. ButtonHtmlクラスを開き、中央のボタンb2に関連するすべてのコードを削除します。

  18. 例7-15に示すように、イメージdown.gifb1(「Disable FX」ボタン)およびb3(「Enable FX」ボタン)ボタンに使用します。

    例7-15

    ImageIcon buttonIcon = createImageIcon("images/down.gif");
    b1 = new JButton("<html><center><b><u>D</u>isable</b><br>"
                             + "<font color=#ffffdd>FX button</font>", 
                             buttonIcon);
    b3 = new JButton("<html><center><b><u>E</u>nable</b><br>"
                             + "<font color=#ffffdd>FX button</font>", 
                             buttonIcon);
    
  19. 例7-16に示すようにactionPerformedメソッドを変更して、fxbuttonの無効化と有効化を実装します。JavaFXボタンの無効化と有効化は、JavaFXアプリケーション・スレッド上で発生する必要があることに注意してください。

    例7-16

    @Override
    public void actionPerformed(ActionEvent e) {
        if ("disable".equals(e.getActionCommand())) {
            Platform.runLater(() -> {
                EnableFXButton.fxbutton.setDisable(true);
            });
            b1.setEnabled(false);
            b3.setEnabled(true);
        } else {
            Platform.runLater(() -> {
                EnableFXButton.fxbutton.setDisable(false);
            });
            b1.setEnabled(true);
            b3.setEnabled(false);
        }
    }
    
  20. [Ctrl] (または[Cmd])キーと[Shift]キーを押しながら[I]キーを押して、例7-17に示すimport文を追加します。

    例7-17

    import javafx.application.Platform;
    
  21. アプリケーションを実行し、Swingボタンをクリックして、図7-3に示すように、JavaFXボタンを無効および有効にします。

JavaFXボタンを使用したSwingボタンの操作

EnableFXButtonアプリケーションをさらに変更し、JavaFXボタンをクリックするとSwingボタンがアクティブ化されるように、JavaFXボタンのsetOnActionメソッドを実装できます。図7-4に、変更済のアプリケーション(EnableButtons)を示します。

図7-4 ボタンの有効化のサンプル

図7-4の説明が続きます
「図7-4 ボタンの有効化のサンプル」の説明

EnableButtonsアプリケーションを作成するには、次の手順を実行します。

  1. EnableFXButtonプロジェクトをコピーし、EnableButtonsという名前の下に保存します。

  2. EnableFXButtonクラスの名前をEnableButtonsに変更し、enablefxbuttonパッケージの名前をenablebuttonsに変更します。

  3. ButtonHtmlおよびEnableButtonsクラスの両方のパッケージ文を修正します。

  4. EnableButtonsクラスを開き、例7-18に示すように、paneFlowPaneクラスのインスタンスにします。

    例7-18

    FlowPane pane = new FlowPane();
    
  5. 例7-19に示すように、イメージleft.gifを使用するようにfxButtonIcon変数の初期化を変更します。

    例7-19

    Image fxButtonIcon = new Image(
    getClass().getResourceAsStream("images/left.gif"));
    
  6. 例7-20に示すように、fxbuttonのテキスト、ツールチップおよびフォント・サイズを変更し、disablePropertyをtrueに設定します。

    例7-20

    fxbutton = new Button("Enable JButton", new ImageView(fxButtonIcon));
    fxbutton.setTooltip(
    new Tooltip("Click this button to enable the Swing button."));
    fxbutton.setStyle("-fx-font: 18 arial; -fx-base: #cce6ff;");
    fxbutton.setDisable(true);
    
  7. 例7-21に示すようにラムダ式を使用することによって、setOnActionメソッドを実装します。イベント・ディスパッチ・スレッド上のSwingオブジェクトのみを変更する必要があることに注意してください。

    例7-21

    fxbutton.setOnAction(ActionEvent e) {
        SwingUtilities.invokeLater(() -> {
            ButtonHtml.b1.setEnabled(true);
        });
        fxbutton.setDisable(true);
        }
    });
    

    注意:

    b1を有効にする行の左側に表示されるエラー・マークは無視してください。このエラーは手順11で修正します。

  8. [Ctrl] (または[Cmd])キーと[Shift]キーを押しながら[I]キーを押して、import文をjavafx.event.ActionEventクラスに追加します。

  9. 例7-22に示すように、swingNodeおよびfxbuttonオブジェクトをレイアウト・コンテナに追加します。

    例7-22

    pane.getChildren().addAll(swingNode, fxbutton);
    
  10. 例7-23に示すように、アプリケーション・タイトルをEnable Buttons Sampleに変更します。

    例7-23

    stage.setTitle("Enable Buttons Sample");
    
  11. ButtonHtmlクラスを開き、b1ボタンの修飾子をpublic staticに変更します。EnableButtonsクラス内のエラー・マークが表示されなくなります。

  12. b3ボタンに関連するすべてのコードと、b1のアクション・コマンドを設定する行を削除します。

  13. 例7-24に示すようにラムダ式を使用することによって、actionPerformedメソッドを変更します。

    例7-24

    @Override
    public void actionPerformed(ActionEvent e) {
        Platform.runLater(() -> {
            EnableButtons.fxbutton.setDisable(false);
        });
        b1.setEnabled(false);
    }
    

まとめ

この章では、既存のSwingコンポーネントをJavaFXアプリケーションに埋め込み、SwingオブジェクトとJavaFXオブジェクト間の相互運用性を提供する方法について学習しました。SwingコンテンツをJavaFXアプリケーションに埋め込む機能を使用すると、開発者は、ソース・コードを保持していない複雑なサード・パーティのSwingコンポーネントを使用するSwingアプリケーションや、メンテナンス・モードでのみ実行されるレガシー・モジュールを含むアプリケーションを移行できるようになります。

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

ソース・コード 

NetBeansプロジェクト 

ウィンドウを閉じる

目次

JavaFX: 相互運用性

展開 | 縮小