ドキュメント



JavaFX: 相互運用性

3 SwingアプリケーションへのJavaFXの統合

この章では、JavaFXコンテンツをSwingアプリケーションに追加する方法と、1つのアプリケーション内でSwingおよびJavaFXコンテンツの両方を動作させるときにスレッドを正しく使用する方法について説明します。

JavaFX SDKでは、JFXPanelクラスが提供されます。このクラスはjavafx.embed.swingパッケージに含まれており、これを使用すると、JavaFXコンテンツをSwingアプリケーションに埋め込むことができるようになります。

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

この章で使用するために、JFrameコンポーネントを作成し、そこにJFXPanelオブジェクトを追加した後、JavaFXコンテンツを含むJFXPanelコンポーネントのグラフィカル・シーンを設定します。

他のSwingアプリケーションの場合と同様、グラフィカル・ユーザー・インタフェース(GUI)はイベント・ディスパッチ・スレッド(EDT)上で作成します。例3-1に、JFrameコンポーネントを作成し、そこにJFXPanelオブジェクトを追加する、initAndShowGUIメソッドを示します。JFXPanelクラスのインスタンスを作成すると、JavaFXランタイムが暗黙的に起動します。GUIの作成後、initFXメソッドをコールして、JavaFXアプリケーション・スレッド上でJavaFXシーンを作成します。

例3-1

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Test {

    private static void initAndShowGUI() {
        // This method is invoked on the EDT thread
        JFrame frame = new JFrame("Swing and JavaFX");
        final JFXPanel fxPanel = new JFXPanel();
        frame.add(fxPanel);
        frame.setSize(300, 200);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                initFX(fxPanel);
            }
       });
    }

    private static void initFX(JFXPanel fxPanel) {
        // This method is invoked on the JavaFX thread
        Scene scene = createScene();
        fxPanel.setScene(scene);
    }

    private static Scene createScene() {
        Group  root  =  new  Group();
        Scene  scene  =  new  Scene(root, Color.ALICEBLUE);
        Text  text  =  new  Text();
        
        text.setX(40);
        text.setY(100);
        text.setFont(new Font(25));
        text.setText("Welcome JavaFX!");

        root.getChildren().add(text);

        return (scene);
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                initAndShowGUI();
            }
        });
    }
}

SwingとJavaFXの相互運用性とスレッド

1つのアプリケーション内でJavaFXとSwingのデータが共存する場合、相互運用性に関する次の状況が発生する可能性があります。

  • JavaFXデータの変更がSwingデータの変更によってトリガーされる。

  • Swingデータの変更がJavaFXデータの変更によってトリガーされる。

Swingデータの変更に応じたJavaFXデータの変更

JavaFXデータには、JavaFXユーザー・スレッド上でのみアクセスする必要があります。JavaFXデータを変更する必要がある場合、例3-2に示すように、コードをRunnableオブジェクト内にラップし、Platform.runLaterメソッドをコールします。

例3-2

jbutton.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent e) { 
        Platform.runLater(new Runnable() { 
            @Override
            public void run() {
                fxlabel.setText("Swing button clicked!"); 
            }
        });
    }
});

JavaFXデータの変更に応じたSwingデータの変更

Swingデータは、EDT上でのみ変更する必要があります。コードがEDT上で実装されるようにするには、例3-3に示すように、コードをRunnableオブジェクト内にラップし、SwingUtilities.invokeLaterメソッドをコールします。

例3-3

SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        //Code to change Swing data.
    }
});

SimpleSwingBrowserアプリケーションについて

SwingとJavaFXの相互運用性がどのように実現されるかを理解するために、SimpleSwingBrowserアプリケーションについて考えてみましょう。これは、Webページを表示するためのJavaFXコンポーネントが統合されたSwingアプリケーションです。URLをアドレス・バーに入力すると、ロードされたページをアプリケーション・ウィンドウに表示できます。SimpleSwingBrowserアプリケーションのウィンドウを図3-1に示します。

図3-1 SimpleSwingBrowserアプリケーションのウィンドウ

図3-1の説明が続きます
「図3-1 SimpleSwingBrowserアプリケーションのウィンドウ」の説明

Swingデータの初期化

SimpleSwingBrowser.javaファイルを表示するか、SimpleSwingBrowser.zipファイルをNetBeansプロジェクトとともにダウンロードできます。ファイルをzipファイルからローカル・ファイルシステム上のディレクトリに抽出し、プロジェクトをNetbeans IDE内で実行します。

NetBeans IDEのバージョン7.2以降、JavaFXコンテンツを埋め込んだSwingアプリケーションがサポートされます。新しいプロジェクトの作成時に、「JavaFX」カテゴリの「JavaFX in Swingアプリケーション」を選択します。

注意:

ファイアウォールの内側からこのアプリケーションを実行する場合、アプリケーションがリモート・リソースにアクセスできるように、プロキシ設定を指定する必要があります。

NetBeans IDEで、「プロジェクト」ウィンドウのSimpleSwingBrowserプロジェクトを右クリックし、「プロパティ」を選択した後、「プロジェクト・プロパティ」ダイアログで、「実行」を選択します。

「VMオプション」フィールドで、次の形式のプロキシを設定します。

-Dhttp.proxyHost=webcache.mydomain.com -Dhttp.proxyPort=8080

SimpleSwingBrowserアプリケーションのGUIは、アプリケーションの起動時にEDT上で作成されます。mainメソッドは、例3-4に示すように実装されます。

例3-4

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            SimpleSwingBrowser browser = new SimpleSwingBrowser();
            browser.setVisible(true);
            browser.loadURL("http://oracle.com");
        }
    });
}

例3-5に示すように、SimpleSwingBrowserクラスは、Swingオブジェクトを初期化し、initComponentsメソッドをコールしてGUIを作成します。

例3-5

public class SimpleSwingBrowser extends JFrame {

    private final JFXPanel jfxPanel = new JFXPanel();
    private WebEngine engine;
    
    private final JPanel panel = new JPanel(new BorderLayout());
    private final JLabel lblStatus = new JLabel();

    private final JButton btnGo = new JButton("Go");
    private final JTextField txtURL = new JTextField();
    private final JProgressBar progressBar = new JProgressBar(); 

    public SimpleSwingBrowser() {
        super();
        initComponents();
    }

    private void initComponents() {
        createScene();
    
        ActionListener al = new ActionListener() {
            @Override 
            public void actionPerformed(ActionEvent e) {
                loadURL(txtURL.getText());
            }
        };

        btnGo.addActionListener(al);
        txtURL.addActionListener(al);

        progressBar.setPreferredSize(new Dimension(150, 18));
        progressBar.setStringPainted(true);

        JPanel topBar = new JPanel(new BorderLayout(5, 0));
        topBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
        topBar.add(txtURL, BorderLayout.CENTER);
        topBar.add(btnGo, BorderLayout.EAST);

        JPanel statusBar = new JPanel(new BorderLayout(5, 0));
        statusBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
        statusBar.add(lblStatus, BorderLayout.CENTER);
        statusBar.add(progressBar, BorderLayout.EAST);

        panel.add(topBar, BorderLayout.NORTH);
        panel.add(jfxPanel, BorderLayout.CENTER);
        panel.add(statusBar, BorderLayout.SOUTH);

        getContentPane().add(panel);

        setPreferredSize(new Dimension(1024, 600));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
    }
}

このアプリケーションの最上部のウィンドウは、テキスト・フィールド、ボタン、進行状況バー、JavaFXコンテンツを表示するためのJFXパネルなど、様々なSwingコンポーネントを含むJFrameオブジェクトです。

JavaFXコンテンツのロード

初回実行時には、http://oracle.comのWebページがWebViewオブジェクト内にロードされます。新しいURLをアドレス・バーに入力すると、initComponentsメソッドのtxtURLテキスト・フィールドにアタッチされたアクション・リスナーが、例3-6に示すように、ページのロードを開始します。

例3-6

ActionListener al = new ActionListener() {
    @Override public void actionPerformed(ActionEvent e) {
        loadURL(txtURL.getText());
    }
};

JavaFXデータには、JavaFXアプリケーション・スレッド上でアクセスする必要があります。例3-7に示すように、loadURLメソッドは、コードをRunnableオブジェクト内にラップし、Platform.runLaterメソッドをコールします。

例3-7

public void loadURL(final String url) {
    Platform.runLater(new Runnable() {
        @Override public void run() {
            String tmp = toURL(url);

            if (url == null) {
            tmp = toURL("http://" + url);
            }

           engine.load(tmp);
        }
    });
}

private static String toURL(String str) {
    try {
        return new URL(str).toExternalForm();
    } catch (MalformedURLException exception) {
        return null;
    }
}

Swingデータの更新

新しいページをWebViewコンポーネント内にロードするときに、ページのタイトルがJavaFXデータから取得されてSwing GUIに渡され、アプリケーション・ウィンドウ上にタイトルとして配置されます。この動作は、例3-8に示すように、createSceneメソッド内に実装されます。

例3-8

private void createScene() {

    Platform.runLater(new Runnable() {
        @Override
        public void run() {

            WebView view = new WebView();
            engine = view.getEngine();

            engine.titleProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, 
String oldValue, final String newValue) {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override 
                        public void run() {
                            SimpleSwingBrowser.this.setTitle(newValue);
                        }
                    });
                }
            });
        }
    });
}

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

ソース・コード 

NetBeansプロジェクト 

ウィンドウを閉じる

目次

JavaFX: 相互運用性

展開 | 縮小