JavaFX 程式架構
JavaFX Scene Builder 與 FXML << 前情 JavaFX 1.X是以JavaFX Script的形式撰寫程式,其副檔名為fx: import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.text.Text; import javafx.scene.text.Font; Stage { title: "First JavaFX" width: 250 height: 80 scene: Scene { content: Text { font: Font { size: 16 } x: 10, y: 30 content: "Hello World - JavaFX" } } } 接著以JavaFX編譯器 (javafxc.exe) 編譯JavaFX Script,由於JavaFX 1.X同時支援桌上型應用程式 (Desktop Profile) 與手機應用程式 (Mobile Profile),因此其編譯方式可分為:
執行JavaFX類別,則以JavaFX直譯器 (javafx.exe) 執行類別檔案,執行方式亦可分為:
但由於JavaFX Script與傳統Java差異甚多,開發人員需花費較多的時間學習,也因此JavaFX Script並未受到很大的重視。 至JavaFX 2.0,Oracle將JavaFX重新改寫,以Java語法取代原JavaFX Script語法與移除支援手機的Mobile版本,並正式併入Java SE 7 Update 6中,將原有的JavaFX編譯器 (javafxc.exe) 與直譯器 (javafx.exe),以Java編譯器 (javac.exe) 與直譯器 (java.exe) 取代,因此可使用同一個編譯器編譯Java與JavaFX程式。 開發JavaFX應用程式需繼承javafx.application.Application抽象類別,Application抽象類別類似於Java Swing的JApplet類別,同樣有其「生命週期」,分別為:
其程式架構如下: import javafx.application.Application; import javafx.scene.Scene; import javafx.stage.Stage; ... // 繼承javafx.application.Application抽象類別 public class JavaFXHelloWorld extends Application { @Override public void start(Stage primaryStage) { ... } public static void main(String[] args) { launch(args); } } JavaFX同樣以main()方法為進入點,但由於JavaFX可同時以視窗程式、Java Applet或以Java Web Start啟動等形式執行,因此其程式架構類似於Java Applet,但較Java Applet精簡。由於視窗程式是以main()方法為進入點,因此在main()中執行Application抽象類別的launch()方法,啟動獨立的JavaFX應用程式,則以視窗的形式執行;若是以Java Applet形式執行,則將不會執行main(),而是由Application抽象類別的start()方法開始,因此上述的程式架構可同時滿足視窗程式、Java Applet與以Java Web Start啟動等形式,一舉數得。 請參考以下範例: import javafx.application.Application; import javafx.scene.Scene; import javafx.stage.Stage; import javafx.scene.text.Text; import javafx.scene.Group; // 繼承javafx.application.Application抽象類別 public class JavaFXHelloWorld extends Application { @Override public void start(Stage primaryStage) { Text text = new Text("("JavaFX Hello World"); text.setX(50); text.setY(50); Group group = new Group(); group.getChildren().add(text); // 設定Scene的Layout Pane Scene scene = new Scene(group); // 設定Stage的標題 primaryStage.setTitle("JavaFX Hello World"); // 設定Stage的寬度 primaryStage.setWidth(250); // 設定Stage的高度 primaryStage.setHeight(200); primaryStage.setScene(scene); // 顯示Stage primaryStage.show(); } public static void main(String[] args) { launch(args); } } JavaFX以樹狀架構的方式組合物件,如同分層堆疊一般,各樹狀節點稱為Node,分為以下三類:
其中javafx.stage.Stage為JavaFX最上層的容器 (Container),類似於Java Swing的JRootPane類別,用以置放Scene物件。javafx.scene.Scene則是JavaFX Scene Graph,可藉以繪圖或配置各類GUI物件。 程式完成之後,同樣以Java編譯器 (javac.exe) 與直譯器 (java.exe) 編譯JavaFX程式與執行類別檔案。 以下為以視窗的形式執行的結果,與Java Swing不同的是,JavaFX會自動處理部份的視窗事件如關閉視窗: 由於JavaFX所開發的應用程式,可同時以Java Applet、Java Web Start與視窗應用程式的形式執行,因此其建立Java Archive的方式與一般的Java程式不同,並非以jar.exe建立,而是以javafxpackager.exe建立JAR檔案,稱為JavaFX Packager。 JavaFX Packager除了將類別、圖像等檔案建立JAR檔案之外,並分別產生執行Java Applet與Java Web Start所需的HTML網頁與JNLP檔案,可省去開發人員自行建立的步驟,此一概念稱為「Write Once, Deploy Anywhere」。 以JavaFX Packager建立JAR的方式可分為:
例如以下指令將同時建立JAR檔案、HTML與JNLP檔案,並設定輸出目錄為dist、Java Applet於網頁中的高度與寬度均為200: javafxpackager -deploy -appclass JavaFXHelloWorld -srcdir . -outdir dist -outfile JavaFXHelloWorld -width 200 -height 200 -name JavaFXHelloWorld -v 以下為JavaFX Packager所產生的HTML網頁內容,與一般以標籤定義Java Applet不同,此外並包含執行JNLP的超連結: <html> <head> <script src="http://java.com/js/dtjava.js"></script> <script> function launchApplication(jnlpfile) { dtjava.launch ( { url : 'JavaFXHelloWorld.jnlp' }, { javafx : '2.2+' }, {} ); return false; } </script> <script> function javafxEmbed() { dtjava.embed ( { url : 'JavaFXHelloWorld.jnlp', placeholder : 'javafx-app-placeholder', width : 200, height : 200 }, { javafx : '2.2+' }, {} ); } <!-- Embed FX application into web page once page is loaded --> dtjava.addOnloadCallback(javafxEmbed); </script> </head> <body> <h2>Test page for <b>JavaFXHelloWorld</b></h2> <b>Webstart:</b> <a href='JavaFXHelloWorld.jnlp' onclick="return launchApplication('JavaFXHelloWorld.jnlp');"> click to launch this app as webstart </a> <br><hr><br> <!-- Applet will be inserted here --> <div id='javafx-app-placeholder'></div> </body> </html> 以下為JavaFX Packager所產生的JNLP內容,除了原有的JNLP標籤之外,並新增<jfx:javafx-runtime>與<jfx:javafx-desc>之XML標籤,分別定義JavaFX執行Runtime Environment的版本與JavaFX類別名稱及長寬: <?xml version="1.0" encoding="utf-8"?> <jnlp spec="1.0" xmlns:jfx=http://javafx.com href="JavaFXHelloWorld.jnlp"> <information> <title>Sample JavaFX Application</title> <vendor>Unknown vendor</vendor> <description>Sample JavaFX 2.0 application.</description> <offline-allowed/> </information> <resources> <jfx:javafx-runtime version="2.2+" href="http://javadl.sun.com/webapps/download/ GetFile/javafx-latest/windows-i586/javafx2.jnlp"/> </resources> <resources> <j2se version="1.6+" href="http://java.sun.com/products/autodl/j2se"/> </resources> <applet-desc width="200" height="200" main-class="com.javafx.main.NoJavaFXFallback" name="JavaFXHelloWorld" > <param name="requiredFXVersion" value="2.2+"/> </applet-desc> <jfx:javafx-desc width="200" height="200" main-class="JavaFXHelloWorld" name="JavaFXHelloWorld" /> <update check="background"/> </jnlp> 除了以標準的Java格式撰寫JavaFX程式之外,JavaFX並提供Builder類別,透過Builder類別可精簡程式長度,但程式的撰寫方式與以往的Java程式不同。請參考以下範例以Builder的方式改寫上述範例: import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.SceneBuilder; import javafx.stage.Stage; import javafx.scene.text.TextBuilder; import javafx.scene.GroupBuilder; // 繼承javafx.application.Application抽象類別 public class JavaFXHelloWorld extends Application { @Override public void start(Stage primaryStage) { Scene scene = SceneBuilder.create() .width(250) .height(200) .root( GroupBuilder.create() .children( TextBuilder.create() .x(50) .y(50) .text("JavaFX Hello World") .build() ) .build() ) .build(); // 設定Stage的標題 primaryStage.setTitle("JavaFX Hello World"); primaryStage.setScene(scene); // 顯示Stage primaryStage.show(); } public static void main(String[] args) { launch(args); } } 除了上述兩種格式之外,另外尚有GroovyFX、ScalaFX與Visage,同樣可開發JavaFX應用程式,其程式長度更為精簡。請分別參考以下網站之介紹:
以下為以GroovyFX改寫上述範例: start { stage(title: 'JavaFX Hello World', visible: true) { scene(width: 250, height: 200) { group() { text(x: 50, y: 50, text: "JavaFX Hello World") } } } } 以下為以ScalaFX改寫上述範例: object HelloJavaOne extends JFXApp { stage = new Stage { title = "JavaFX Hello World" width = 250 height = 200 scene = new Scene { Text { x = 50 y = 50 text = "JavaFX Hello World" } } } } 以下為以Visage改寫上述範例: Stage { title: "JavaFX Hello World" width: 250 height: 200 scene: Scene { content: Text { x: 50 y: 50 text: "JavaFX Hello World" } } } 【參考資料】 [1] Java Official Web Site |