原文地址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的資料只能通過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 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 查看。