JavaFX – Hands On

The JavaFX 1.0 release was launched in December 2008 after
years of development. So what is it? Sun markets JavaFX as a
Rich Internet Application (RIA) platform and a tools suite aimed
both for developers and UI designers. In this sense JavaFX can be
compared with Adobe Flash and Microsoft Silverlight.

With JavaFX a new programming language called JavaFX Script
was introduced. In this article we’ll take a closer look at this new
language.

JavaFX will be able to run on PCs, mobile devices and TV screens. Things have
been moving pretty fast with JavaFX 1.1 released just two months after 1.0
and in early June 2009 a 1.2 version was released. The modifications have been
substantial affecting both the API and the language syntax. It seems that Sun is
using the opportunity to fix early mistakes in JavaFX before it is stabilized. This
seems like a very good idea to avoid mistakes like those that will forever haunt
standard Java.

HelloWorld

Let’s start with the traditional HelloWorld example. As you may have guessed
JavaFX Script is very closely related to Java. In fact JavaFX scripts are compiled
into standard Java .class files by the java fx compiler. A major advantage of this
approach is that the JVM, which is available for many platforms, can be used.
Now let’s see some code. Create a new file called helloworld.fx with following
contents:

println(”Hello JavaFX”);

Compile the file with the javafxc compiler

javafxc helloworld.fx

The javafxc compiler have created a standard java class file:

helloworld.class

Now what happens if we try to run the program with java?

java helloworld
Exception in thread ”main” java.lang.NoClassDefFoundError: com/sun/javafx/
runtime/FXObject

That’s not quite the intended result… To run a JavaFX script the javafx tool is used. It is a java launcher that configures the runtime environment so that the classes used by JavaFX are included:

javafx helloworld

This time the output shouldn’t surprise anyone:

Hello JavaFX

A Closer Look

In the simple hello world example we didn’t declare a class or a main function.
A JavaFX script can contain any number of classes or loose statements. JavaFX
script is a statically typed language just like the Java language.

Variables

A variable is declared with the var keyword and can optionally specify a type.
Unlike Java all types (even primitives) are backed by classes so you can call
methods on them.

var age: Integer; // type explicitly stated
age = 7;
var name = ”Foo”; // name gets the type String
name = ”Bar”;     // ok
name = 7;         // This results in a compile error since name is a String

Classes

Classes in JavaFX differs from Java class. Lets have a look at simple example.

class Person{
  var name : String;
  var age : Integer;
} 

You may have noticed that the the Person class didn’t have a constructor. Objects
in JavaFX are created with the initialization arguments named. Also note that
the keyword new is missing:

var person = Person{name:”Joe”, age:21}

Sequences

Sequences is a kind of Java arrays on steroids. They are used in many places in
the language and can contain zero or more elements of a type.

var nums = [1..5];
insert 6 into nums;
println(nums);     // prints [ 1, 2, 3, 4, 5, 6 ]

Duration

The Duration type is very handy for calculations regarding time:

var twoSeconds = 2s;
var oneHourAndABit = 1h + twoSeconds;

Function Types

Functions are first class objects in JavaFX. In the example below the
timesNWithBonus function returns another function that has access to the
argument n and the variable bonus. The variable timesTenWithBonus holds a
reference to the returned function and the reference is later used to invoke the
function and print the result.

function timesNWithBonus(n: Integer): function(:Integer): Integer {
  var bonus=2;
  function(x: Integer): Integer { x * n + bonus}
}
var timesTenWithBonus = timesNWithBonus(10);
println(timesTenWithBonus(4));    // prints 42 (10 * 4 + 2)

Binding

Binding makes it possible connect or bind a variable value to some some
expression.

function square(x:Integer):Integer{ return x*x };
var y = 3;
var sqY = bind square(y);
println(sqY); // prints 9
y=4;
println(sqY); // prints 16

Calling Home

It’s easy to use Java objects from JavaFX. In this example we use the java.util.
Random class but the syntax would be the same if you were to use your own
existing Java libraries.

var rand = new java.util.Random();
var randNbr = rand.nextInt(6);
println(”Random number: {randNbr}”); 

As shown in the last line you can use braces in a string to evaluate an expression.

Graphics in JavaFX

One of the main goals with JavaFX is to make it easy to create an application’s
UI. To accomplish this goal a declarative approach is used. This has the benefit
that the structure of JavaFX script code can be kept similar to what is actually
drawn on the screen. To give an idea of how this works we will walk through the
creation of a simple application showing a circle and a text.

Preparing the Stage

The application window is referred to as a stage. To open a window you simply
state that there should be one and it will be opened for you when the application
starts. The following code opens a window with …well really nothing inside:

Stage {
    title: ”Jayview FX”
    width: 200
    height: 250
    scene: Scene {
        fill: Color.BLACK
        content: []
    }
} 

As you can see in the code a scene is declared inside the stage. The scene is the
area that you can draw on inside the application window. JavaFX will draw all
graphical objects placed inside a scene; however the example’s content is empty
so the result is a black background.

Making a Scene

To make the application more interesting we add a circle and some text to the
scene. This is done by simply adding them to the scene’s content variable:

scene: Scene {
        fill: Color.BLACK
        content: [
            Circle {
                centerX: 100
                centerY: 100
                radius: 50
                fill: Color.RED
            },
            Text{
                content: ”Jayview!”
                x: 75
                y: 100
                fill: Color.WHITE
            }
        ]
    } 

The Text and Circle classes inherit from the Node class which contains basic graphical stuff like positioning, scaling and rotating. Graphical objects are
organized in a tree structure of Node objects called a scene graph in which the
scene is the root. Now that we have both a circle and a text, what more could
you possibly want?

Effects

If you have used image effects in Java you know that quite a lot of code is
required to achieve effects like reflections. In JavaFX this has been addressed by
image filters providing effects like blur, shadow lighting and glow. In our example
we want the circle and text to have a reflection. To treat multiple nodes as one
when applying an effect a Group is needed. A Group has a content attribute
in which you place the nodes that should be treated together, so the circle and
text is moved inside it. Following the content we declare that a reflection effect
should be applied on it:

Group{
    content: [
        // Circle and text code goes here...
    ]
    effect: Reflection {
        fraction: 0.9   // 90% of the image visible
        topOpacity: 0.5 // 50% is max opacity
        topOffset: 2.5  // Offset between node end and reflection
    }
}

Animations Step One – Binding Variables

Combining the declarative UI and data binding is very useful for creating
animations. In this example we want to modify the circle’s color and radius so
therefore declare two variables:

var fancyColor = Color.RED;
var circleRadius = 50;

To bind the circle’s color and radius to the new variables it is modified to use
the bind expression:

Circle {
    centerX: 100
    centerY: 100
    radius: bind circleRadius
    fill}

Let’s also modify the text to show the circle’s radius and align its y-position with
the circle:

Text{
    content: bind ”Radius{circleRadius}”
    x: 75
    y: bind 100 + circleRadius
  } 

When the variables circleRadius or fancyColor change JavaFX will automatically
redraw the circle using the new values.

Animations Step Two – Let’s Get Moving

Animations are controlled by a Timeline which can be started and stopped. The
time line contains a sequence of key frames, but lets start with an empty time
line:

var timeline = Timeline {
    autoReverse: true // Play in reverse when reaching the end
    repeatCount: Timeline.INDEFINITE
    keyFrames: []
}
timeline.play();

A key frame contains information about what the scene should look like at a
specific point in time, typically the end and beginning of the animation. First we
add the animation’s start to the keyFrames sequence:

KeyFrame {
    time: 0s  // 0 seconds into the animation
    values: [
        fancyColor => Color.RED tween Interpolator.EASEBOTH,
        circleRadius => 50 tween Interpolator.EASEBOTH
    ]} 

The syntax used for the values sequence may look strange but is easy to read
when you get used to it:

variable => value at the time of the key frame tween method for calculating
variable values between frames

To make an animation look smooth acceleration and deceleration is used to
prevent changes from appearing jerky. JavaFX provides built in support for this
using Interpolator.EASEBOTH. In a similar way we define what the color and
radius values should be at 5 seconds:

KeyFrame {
    time: 5s
    values: [
        fancyColor => Color.YELLOW tween Interpolator.EASEBOTH,
        circleRadius => 0 tween Interpolator.EASEBOTH
    ]
} 

The application is now complete with an animated circle and radius readout.
The images below show the shrinking circle, but don’t worry it comes back
again ;).

Radius

Example Code

The complete example code (excluding import statements) is shown below to
give a better overview:

var fancyColor =  Color.RED;
var circleRadius = 50;
Stage {
    title: ”Jayview FX”
    width: 200
    height: 250
    scene: Scene {
        fill: Color.BLACK
        content: [
            Group{
                content: [
                    Circle {
                        centerX: 100
 centerY: 100
                        radius: bind circleRadius
                        fill: bind fancyColor
                    }
                    Text{
                        content: bind ”Radius {circleRadius}”
                        x: 50
                        y: bind 100 + circleRadius
                        fill: Color.WHITE
                    }
                ]
                effect: Reflection {
                    fraction: 0.9
                    topOpacity: 0.5
                    topOffset: 2.5
                }
            }
        ]
    }
}
var timeline = Timeline {
    autoReverse: true
    repeatCount: Timeline.INDEFINITE
    keyFrames: [
        KeyFrame {
            time: 0s
            values: [
                fancyColor => Color.RED tween Interpolator.EASEBOTH,
                circleRadius => 50 tween Interpolator.EASEBOTH
            ]
        },
        KeyFrame {
            time: 5s
            values: [
                fancyColor => Color.YELLOW tween Interpolator.EASEBOTH,
                circleRadius => 0 tween Interpolator.EASEBOTH
            ]
        }
    ]
};
timeline.play(); 

Conclusion

First of all JavaFX is fun to play with! We really think you should download it
and try it out to see for yourself. The new syntax does take some time to get used
to but the Netbeans IDE gives good support to get started.

You can tell that JavaFX is still an early version, the documentation isn’t complete
and the tools for designers do not yet match competing tools like Adobe Flash.
Sun is currently addressing these shortcomings and when JavaFX reaches a more
mature level it may well become the default choice for creating rich Internet
applications that it strives to be.

Per Böckman
Mattias Lindskog

References

Originally published in JayView.

This Post Has One Comment

  1. At least some bloggers can still write. My thanks for this piece of writing..

Leave a Reply

Close Menu