Friday Jun 19, 2009

FXD Details (1): FXZ Loading

JavaFX Content File Loading

Once you export your graphic assets from the Adobe Photoshop or Illustrator, you will need to load it to the JavaFX. Here are the various ways loading it depending on what you want to do.  

1) Synchronous Load

JavaFX content file (FXZ) or data file (FXD) can be loaded synchronously by using the following approaches. As FX event thread will be blocked until synchronous loading is completed, this approach maybe good for the local loading only.

A) FXDLoader.load():Node

The simplest form. It is useful when the content of the FXZ file is ready for use as it is, that is, no need of manipulation such as scaling, adding effects, etc from JavaFX code. The returned node is actually a Group node whose parent is null. It can be directly added to another branch of the scene. 

Example 1:
insert FXDLoader.load("{__DIR__}fxsample.fxz") into scene.content;

B) FXDLoader.loadContent():FXDContent

This approach is usually used when the content of the FXZ file needs some touch-up from JavaFX code such as scaling, adding effects, etc. Note that all other getter functions except getRoot() return a child node whose parent is already set to the top level Group in the FXZ content. Since a node with a non-null parent can not be reused in a different parent, the node should be removed from the old parent or its clone should be used. The Duplicator class comes in place for this purpose.

 Example 1:
 var fxdContent:FXDContent = FXDLoader.loadContent("{__DIR__}fxsample.fxz");
 scene.content = fxdContent.getRoot();

 Example 2:
var fxdContent:FXDContent = FXDLoader.loadContent("{__DIR__}fxsample.fxz");
 scene.content = Duplicator.duplicate(fxdContent.getNode("atom"));

2) Asynchronous Load

JavaFX content file (FXZ) or data file (FXD) can be loaded asynchronously as well by using the following approaches. This approach is recommended for the network loading.

C) FXDLoader.loadOnBackground(url, loader):FXDLoader

This is useful when you want to reuse the same loader to load more than 1 FXZ file as illustrated in the example.

Example 1:
var loader:FXDLoader = FXDLoader {
    onDone: function() {
        if(loader.succeeded) {
            scene.content = loader.content.getRoot();
FXDLoader.loadOnBackground("{__DIR__}fxsample.fxz", loader);

PauseTransition {
    duration: 3s
    action: function() {
        FXDLoader.loadOnBackground("{__DIR__}fifteen.fxz", loader);

D) FXDLoader.createLoader(url):FXDLoader

FXDLoader is extended from javafx.async.Task. If you are familiar with the FX async framework, the following approach should make you feel at home. Please see my other blog about FX Async Operation for details.

 Example 1:
var loader:FXDLoader = FXDLoader.createLoader("{__DIR__}fxsample.fxz");
loader.onDone = function() {
    if(loader.succeeded) {
        insert loader2.content.getRoot() into scene.content;

2) Configurable Synchronous/Asynchronous Load

FXDNode can be configured to load synchronously or asynchronously by using the following approaches. NetBeans IDE has a special support to create a UI class that extends FXDNode for the selected FXZ file. This approach is preferred in most of usecases.

e) FXDNode {backgroundLoading: false} - Synchronous Loading

As in the next case, a loader can be attached only for listening events such as onStart, onDone, etc.

Example 1:
scene.content = FXDNode {
    url: "{__DIR__}fxsample.fxz"
    backgroundLoading: false
    placeholder: Text{ x:10 y: bind scene.height-50 content: "Loading graphics..." fill: Color.YELLOW}

f) FXDNode {backgroundLoading: true} - Asynchronous Loading

A loader can be attached but it is only for listening events such as onStart, onDone, etc. Note that loader.source and loader.content don't have what you might be expecting but null values.

Example 1:
var loader: FXDLoader;
scene.content = FXDNode {
    url: "{__DIR__}fxsample.fxz"
    backgroundLoading: true
    placeholder: Text{ x:10 y: bind scene.height-50 content: "Loading graphics..." fill: Color.YELLOW}
    loader: loader = FXDLoader {
        onStart: function() {
        onDone: function() {
            println("onDone: {loader.source}");             // onDone: null
            println("onDone: {loader.content.getRoot()}");
  // onDone: null

g) Generating a UI Stub File for a JavaFX Graphic in the NetBeans IDE

When a JavaFX Content File (FXZ) is included in a NetBeans project, developers can generate a UI Stub file, which enables them to easily access the graphical elements from JavaFX applications. This UI Stub file defines variables for all of the graphic objects with an ID value. The UI stub file that is generated has the same name as the JavaFX graphic plus a UI suffix. For example, if the JavaFX graphic is named fxsample.fxz, the stub file is named fxsampleUI.fx. The class that is generated also has the name fxsampleUI.

  1. In the NetBeans IDE, open the project for your JavaFX application.
  2. Locate the JavaFX Content File (FXZ) in the Projects pane.
  3. Right-click (or Control-click on the Mac) the JavaFX Content File (FXZ) and select Generate UI stub.

Note that the generated UI class extends FXDNode so its usage is same as above. It's convenient to access the enclosed graphic assests.

Example 1:
var loader: FXDLoader;
var fxdNode:fxsampleUI = fxsampleUI {
    url: "{__DIR__}fxsample.fxz"
    backgroundLoading: true
    placeholder: Text{ x:10 y: bind scene.height-50 content: "Loading graphics..." fill: Color.YELLOW}
    loader: loader = FXDLoader {
        onDone: function() {
            delete fxdNode.atom from fxdNode.getRoot().content;
            scene.content = fxdNode.atom;

NetBean generated fxsampleUI.fx:

import java.lang.\*;
import javafx.scene.Node;
import javafx.fxd.FXDNode;

public class fxsampleUI extends FXDNode {

    override public var url = "{__DIR__}fxsample.fxz";

    public-read protected var atom: Node;
    public-read protected var background: Node;

    override protected function contentLoaded() : Void {

     \* Check if some element with given id exists and write
     \* a warning if the element could not be found.
     \* The whole method can be removed if such warning is not required.
    protected override function getObject( id:String) : Object {
        var obj = super.getObject(id);
        if ( obj == null) {
            System.err.println("WARNING: Element with id {id} not found in {url}");
        return obj;

To be continued...


I am Baechul and live in Santa Clara, U.S.A. This is my blog that will talk about Java and JavaFX technologies.


Top Tags
« June 2016