JavaFX 程式架構 by 黃嘉輝 | CodeData
top

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),因此其編譯方式可分為:

  • 預設方式:javafxc *.fx
  • 桌上型應用程式:javafxc -profile desktop -d desktop *.fx
  • 手機應用程式:javafxc -profile mobile -d mobile *.fx

執行JavaFX類別,則以JavaFX直譯器 (javafx.exe) 執行類別檔案,執行方式亦可分為:

  • 預設方式:javafx JavaFXApplication
  • 顯示啟動圖像:javafx -splash:spash.jpg JavaFXApplication
  • 桌上型應用程式:javafx -profile desktop JavaFXApplication

但由於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類別,同樣有其「生命週期」,分別為:

  • init():初始化JavaFX應用程式。
  • start():為JavaFX應用程式的進入點,在此為Java Applet。
  • launch():啟動獨立 (Standalone) 的JavaFX應用程式,在此為視窗程式。
  • stop():當JavaFX應用程式結束之前,將執行stop()方法。

其程式架構如下:

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,分為以下三類:

  • Root:最上層的容器。
  • Parent:置放物件的容器。
  • Leaf:容器中的物件。

其中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會自動處理部份的視窗事件如關閉視窗:

2-5

由於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的方式可分為:

  • javafxpackager -createbss:將CSS檔案轉為Binary格式。
  • javafxpackager -createjar:僅建立JAR檔案。
  • javafxpackager -deploy:除了JAR之外,並產生HTML與JNLP檔案。
  • javafxpackager -makeall:依序編譯JavaFX程式、建立JAR檔案、產生HTML與JNLP檔案。
  • javafxpackager -signJar:對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
[2] JavaFX
[3] NetBeans
[4] JavaFX 2.2 API Specification.
[5] Java Platform, Standard Edition 7 API Specification.

前情 >> JavaFX 多媒體(1)使用 Audio Clip 播放音訊

分享:
按讚!加入 CodeData Facebook 粉絲群

相關文章

留言

留言請先。還沒帳號註冊也可以使用FacebookGoogle+登錄留言

關於作者

黃嘉輝副教授,目前任職於國立臺北商業大學企業管理學系,喜歡寫程式,特別愛Java,範例可參考教學網站

熱門論壇文章

熱門技術文章