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);
    }
}.play();

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;
    }
}
loader.start();

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() {
            println("onStart");
        }
        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 {
        atom=getNode("atom");
        background=getNode("background");
    }

    /\*\*
     \* 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...

Comments:

Is it already possible to write a scene to FXD?

Posted by Kees on June 20, 2009 at 06:51 PM PDT #

Kees, I have an experimental code which does it, but it is not part of the release, as there are still some minor issues. But generally yes, at some point it will be possible to save a scene to FXD.

Posted by guest on June 22, 2009 at 04:37 AM PDT #

Regarding the last example, NetBean generated fxsampleUI.fx :

What's the recommended way to use the FXZ content (e.g. atom or background) in a Scene?

Adding these to a scene's contents as-is can't be done. It seems they have to be
removed from the parent FXDNode first..

Or is it better to use the Duplicator to create parent-less Nodes?

Posted by Bill on July 13, 2009 at 11:21 PM PDT #

I usually does unparenting whenever possible. An example would be:

var scene = Scene{}
var fxsample:fxsampleUI = fxsampleUI{}
if(fxsample.background.parent instanceof Group) {
delete fxsample.background from (fxsample.background.parent as Group).content;
scene.content = fxsample.background;
} else {
scene.content = Duplicator.duplicate(fxsample.background);
}

Posted by Baechul on July 14, 2009 at 03:46 AM PDT #

Thanks for the tip.

It seems a bit ugly though (from the developer's perspective) to have to re-parent
each Node you want to use.

But anyway, I am just glad I can design in Inkscape and use my drawings in Java!

Posted by Bill on July 14, 2009 at 03:50 AM PDT #

It's probably best to avoid reparenting nodes at all, and instead rearrange the artwork so that you can use the nodes in-place. The advantage of NetBeans' UI stub features is that it gives convenient names to various sub-nodes, so that you can do things like rotate them, add effects, etc. But you can do all this in-place, and you don't have to extract the node and put it somewhere else in the scene graph.

Posted by Stuart Marks on October 12, 2009 at 06:10 PM PDT #

Kees, I have an experimental code which does it, but it is not part of the release, as there are still some minor issues. But generally yes, at some point it will be possible to save a scene to FXD.

Hi, I need to save a scene to FXD, can you tell me how to do it?
Thanks!

Posted by Hector on November 09, 2009 at 02:47 AM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

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

Search

Top Tags
Categories
Archives
« July 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
       
Today