第七回 JavaFX2.0和Swing的集成

原文地址http://download.oracle.com/javafx/2.0/swing/jfxpub-swing.htm

 

JavaFX 2.0 發佈版引入了JFXPanel類,它位於 javafx.embed.swing 包中,使你能夠將JavaFX內容綁定進Swing 程序。

本文教你怎麼將JavaFX內容加進Swing 程序中並指導你如何在一個同時具備Swing 和JavaFX 的應用中正確使用線程。

 

添加JavaFX到Swing組件

 要達到本文的目的,你要創建一個JFrame 組件,並添加一個JFXPanel 對象,JFXPanel組件的圖形場景要包含JavaFX 內容。

和所有的Swing程序一樣,你要在 Event Dispatch Thread (事件調度線程EDT)上創建圖形用戶接口(GUI) 。Example 1 展示了initAndShowGUI 方法,它創建了一個JFrame 組件並添加了JFXPanel 對象。創建JFXPanel 類的實例會在後臺開始JavaFX 運行時。GUI 創建後,調用initFX 方法在JavaFX線程上創建JavaFX場景。

 

Example 1

public class Test {

    private static void initAndShowGUI() {
        // This method is invoked on the EDT thread
        JFrame frame = new JFrame("FX");
        final JFXPanel fxPanel = new JFXPanel();
        frame.add(fxPanel);
        frame.setVisible(true);

        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() {
        //Code to create the JavaFX scene
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
            initAndShowGUI();
            }
        });
    }
}

 

 

JavaFX-Swing的互操作性和線程

由於JavaFX和Swing的數據存在與一個程序中,你可能遇到以下互操作的情況:

  • 一個JavaFX的數據改變是由Swing的數據改變引起的.

  • 反之.

改變JavaFX的數據來回應Swing數據的改變

記住JavaFX的數據只能通過javaFX用戶線程訪問。不論何時要改變JavaFX 數據都要把你的代碼用一個Runnable 對象包圍起來並調用Platform.runLater 方法。見Example 2 .

Example 2

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

改變Swing數據來回應JavaFX 數據的改變

記住Swing數據的改變要通過EDT。確保你的代碼實現了EDT,把它用Runnable 對象環繞並調用SwingUtilities.invokeLater 方法。見Example 3 .

Example 3

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

SwingBrowser2: 一個集成了JavaFX組件的Swing應用

通過SwingBrowser2 可以看到 Swing - JavaFX是怎麼互操作的,它爲瀏覽器提供了常用的基本功能。你可以在它的地址欄中鍵入一個URL 來查看應用窗口加載的頁面。你可以通過點頁面鏈接去到新頁面、返回前一頁、打開標籤頁、加入書籤、全頁面檢索。 Figure 1是該應用的窗口。

Figure 1 The SwingBrowser2 application window

Description of Figure 1 follows
Description of "Figure 1 The SwingBrowser2 application window" 

初始化Swing數據

你可以從一個NB工程中的側邊欄點鏈接來下載swingbrowser2.zip 文件。解壓到本地並從Netbeans IDE中運行爲工程。確保你的NetBeans IDE版本是支持的。

 SwingBrowser2打開後,它的GUI創建就在 EDT上。通過邊欄的鏈接查看 Main.java 文件。

應用的頂層窗口是一個 JFrame 組件,包含了很多Swing 組件,比如一個tabbed面板,一個menu,幾個text field、button,還有一個要顯示JavaFX內容的JFX 面板。

加載 JavaFX內容

剛開始運行,JFX面板包含一個空的WebView 對象。當在地址欄輸入一個URL後, AddressBar.java中的 action listener 就開始加載頁面。代碼見Example 4 .

Example 4

txtURL.addActionListener(new ActionListener() {
    @Override public void actionPerformed(ActionEvent e) {
        browser.load(txtURL.getText());
    }
});

Browser.java文件中的load 方法驗證URL並調用call方法,見 Example 5 .

Example 5

public void load(String str) {
    if (str != null {
        str = str.trim();

        if (str.isEmpty()) return;

        String url = toURL(str);
        if (url == null) {
            url = toURL("http://" + str);
        }
        if (url != null) {
        Platform.runLater (new Runnable() {
            @Override
            public void run () {
     
        call(url);
        }
    }
}

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

JavaFX數據應該只能在JavaFX線程上訪問。call方法驗證了線程並確保特點URL的頁面被加載在 JavaFX線程上。Callback.java 文件中有完整代碼。Example 6 是表明了實現方案的代碼塊。

Example 6

public final void call(final String value) {
    if (Platform.isFXApplicationThread()) {
        callImpl(value);
    }
    else {
        Platform.runLater(new Runnable() {
            @Override public void run() {
                callImpl(value);
            }
        });
    }
}

protected void callImpl(String value) {
    getEngine().load(value);
}

更新Swing數據

當 WebView 組件加載了新頁面後,頁面標題就從JavaFX數據中取回並傳遞給Swing GUI。然後頁面標題就顯示在標籤頁上並加入應用標題。 TabbedBrowser.java 中有完整代碼。Example 7 是表明了實現方案的代碼塊。

Example 7

public WebPane addNewTab(final String url, boolean selected) {
    ...
    final WebPane wp = new WebPane(url);

    wp.getBrowser().getEngine().titleProperty().addListener(
new javafx.beans.value.ChangeListener<String>() {
        @Override
        public void changed(ObservableValue<? extends String> observable, 
String oldValue, final String title) {
            EventQueue.invokeLater(new Runnable() {
                @Override public void run() {
                    setTitleAt(indexOfComponent(wp), title);
                    setToolTipTextAt(indexOfComponent(wp), title);

                    if (getSelectedComponent() == wp) {
                    setWindowTitle(title);
                    }
                }
            )};
        }
    )};
}

想了解怎麼部署二者的整合應用,到 Deploying JavaFX Applications 查看。

發佈了14 篇原創文章 · 獲贊 6 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章