Getting Started with JavaFX

Exclusive offer: get 50% off this eBook here
JavaFX 1.2 Application Development Cookbook

JavaFX 1.2 Application Development Cookbook — Save 50%

Over 60 recipes to create rich Internet applications with many exciting features

$23.99    $12.00
by Vladimir Vivien | October 2010 | Cookbooks Java

This article by Vladimir Vivien, author of JavaFX 1.2 Application Development Cookbook, covers language basics such as classes, data types, function usage, variable declaration, data binding, triggers, Java and JavaFX integration.

In this article, we will cover the following topics:

  • Using javafxc to compile JavaFX Code
  • Creating and using JavaFX classes
  • Creating and using variables in JavaFX
  • Using binding and triggers to update variables
  • Creating and using JavaFX functions
  • Integrating your JavaFX code with Java
  • Creating and using JavaFX sequences
  • Working with JavaFX string

 

JavaFX 1.2 Application Development Cookbook

JavaFX 1.2 Application Development Cookbook

Over 60 recipes to create rich Internet applications with many exciting features

  • Easily develop feature-rich internet applications to interact with the user using various built-in components of JavaFX
  • Make your application visually appealing by using various JavaFX classes—ListView, Slider, ProgressBar—to display your content and enhance its look with the help of CSS styling
  • Enhance the look and feel of your application by embedding multimedia components such as images, audio, and video
  • Part of Packt's Cookbook series: Each recipe is a carefully organized sequence of instructions to complete the task as efficiently as possible

Read more about this book

(For more resources on JavaFX, see here.)

Using javafxc to compile JavaFX code

While it certainly makes it easier to build JavaFX with the support of an IDE (see the NetBeans and Eclipse recipes), it is not a requirement. In some situations, having direct access to the SDK tools is preferred (automated build for instance). This recipe explores the build tools that are shipped with the JavaFX SDK and provides steps to show you how to manually compile your applications.

Getting ready

To use the SDK tools, you will need to download and install the JavaFX SDK. See the recipe Installing the JavaFX SDK, for instructions on how to do it.

How to do it...

Open your favorite text/code editor and type the following code. The full code is available from ch01/source-code/src/hello/HelloJavaFX.fx.

package hello;

import javafx.stage.Stage;
import javafx.scene.Scene
import javafx.scene.text.Text;
import javafx.scene.text.Font;

Stage {
title: "Hello JavaFX"
width: 250
height: 80
scene: Scene {
content: [
Text {
font : Font {size : 16}
x: 10
y: 30
content: "Hello World!"
}
]
}
}

Save the file at location hello/Main.fx.

To compile the file, invoke the JavaFX compiler from the command line from a directory up from the where the file is stored (for this example, it would be executed from the src directory):

javafxc hello/Main.fx

If your compilation command works properly, you will not get any messages back from the compiler. You will, however, see the file HelloJavaFX.class created by the compiler in the hello directory.

If, however, you get a "file not found" error during compilation, ensure that you have properly specified the path to the HelloJavaFX.fx file.

How it works...

The javafxc compiler works in similar ways as your regular Java compiler. It parses and compiles the JavaFX script into Java byte code with the .class extension.

javafxc accepts numerous command-line arguments to control how and what sources get compiled, as shown in the following command:

javafxc [options] [sourcefiles] [@argfiles]

where options are your command-line options, followed by one or more source files, which can be followed by list of argument files. Below are some of the more commonly javafxc arguments:

  • classpath (-cp)—the classpath option specifies the locations (separated by a path separator character) where the compiler can find class files and/or library jar files that are required for building the application.
  • javafxc -cp .:lib/mylibrary.jar MyClass.fx

  • sourcepath—in more complicated project structure, you can use this option to specify one or more locations where the compiler should search for source file and satisfy source dependencies.
  • javafxc -cp . -sourcepath .:src:src1:src2 MyClass.fx

  • -d—with this option, you can set the target directory where compiled class files are to be stored. The compiler will create the package structure of the class under this directory and place the compiled JavaFX classes accordingly.
  • javafxc -cp . -d build MyClass.fx

  • The @argfiles option lets you specify a file which can contain javafxc command-line arguments. When the compiler is invoked and a @argfile is found, it uses the content of the file as an argument for javafxc. This can help shorten tediously long arguments into short, succinct commands.
  • Assume file cmdargs has the following content:

    -d build
    -cp .:lib/api1.jar:lib/api2.jar:lib/api3.jar
    -sourcepath core/src:components/src:tools/src

    Then you can invoke javafxc as:

    $> javafxc @cmdargs

See also

  • Installing the JavaFX SDK

Creating and using JavaFX classes

JavaFX is an object-oriented scripting language. As such, object types, represented as classes, are part of the basic constructs of the language. This section shows how to declare, initialize, and use JavaFX classes.

Getting ready

If you have used other scripting languages such as ActionScript, JavaScript, Python, or PHP, the concepts presented in this section should be familiar. If you have no idea what a class is or what it should be, just remember this: a class is code that represents a logical entity (tree, person, organization, and so on) that you can manipulate programmatically or while using your application. A class usually exposes properties and operations to access the state or behavior of the class.

How to do it...

Let's assume we are building an application for a dealership. You may have a class called Vehicle to represent cars and other type of vehicles processed in the application. The next code example creates the Vehicle class. Refer to ch01/source-code/src/javafx/Vehicle.fx for full listing of the code presented here.

  1. Open your favorite text editor (or fire up your favorite IDE).
  2. Type the following class declaration:
  3. class Vehicle {
    var make;
    var model;
    var color;
    var year;

    function drive () : Void {
    println("You are driving a "
    "{year} {color} {make} {model}!")
    }
    }

  4. Once your class is properly declared, it is now ready to be used. To use the class, add the following (highlighted code) to the file:
  5. class Vehicle {
    ...
    }
    var vehicle = Vehicle {
    year:2010
    color: "Grey"
    make:"Mini"
    model:"Cooper"
    };
    vehicle.drive();

  6. Save the file as Vehicle.fx. Now, from the command-line, compile it with:
  7. $> javafxc Vehicle.fx

    If you are using an IDE, you can simply right, click on the file to run it.

    When the code executes, you should see:

    $> You are driving a 2010 Grey Mini Cooper!

How it works...

The previous snippet shows how to declare a class in JavaFX. Albeit a simple class, it shows the basic structure of a JavaFX class. It has properties represented by variables declarations:

var make;
var model;
var color;
var year;

and it has a function:

function drive () : Void {
println("You are driving a "
"{year} {color} {make} {model}!")
}

which can update the properties and/or modify the behavior (for details on JavaFX functions, see the recipe Creating and Using JavaFX functions). In this example, when the function is invoked on a vehicle object, it causes the object to display information about the vehicle on the console prompt.

Object literal initialization

Another aspect of JavaFX class usage is object declaration. JavaFX supports object literal declaration to initialize a new instance of the class. This format lets developers declaratively create a new instance of a class using the class's literal representation and pass in property literal values directly into the initialization block to the object's named public properties.

var vehicle = Vehicle {
year:2010
color: "Grey"
make:"Mini"
model:"Cooper"
};

The previous snippet declares variable vehicle and assigns to it a new instance of the Vehicle class with year = 2010, color = Grey, make = Mini, and model = Cooper. The values that are passed in the literal block overwrite the default values of the named public properties.

There's more...

JavaFX class definition mechanism does not support a constructor as in languages such as Java and C#. However, to allow developers to hook into the life cycle of the object's instance creation phase, JavaFX exposes a specialized code block called init{} to let developers provide custom code which is executed during object initialization.

Initialization block

Code in the init block is executed as one of the final steps of object creation after properties declared in the object literal are initialized. Developers can use this facility to initialize values and initialize resources that the new object will need. To illustrate how this works, the previous code snippet has been modified with an init block. You can get the full listing of the code at ch01/source-code/src/javafx/Vehicle2.fx.

class Vehicle {
...
init {
color = "Black";
}
function drive () : Void {
println("You are driving a "
"{year} {color} {make} {model}!");
}
}

var vehicle = Vehicle {
year:2010
make:"Mini"
model:"Cooper"
};

vehicle.drive();

Notice that the object literal declaration of object vehicle no longer includes the color declaration. Nevertheless, the value of property color will be initialized to Black in the init{} code block during the object's initialization.

When you run the application, it should display:

You are driving a 2010 Black Mini Cooper!

See also

  • Declaring and using variables in JavaFX
  • Creating and using JavaFX functions

Creating and using variables in JavaFX

JavaFX is a statically type-safe and type-strict scripting language. Therefore, variables (and anything which can be assigned to a variable, including functions and expressions) in JavaFX, must be associated with a type, which indicates the expected behavior and representation of the variable. This sections explores how to create, initialize, and update JavaFX variables.

Getting ready

Before we look at creating and using variables, it is beneficial to have an understanding of what is meant by data type and be familiar with some common data types such as String, Integer, Float, and Boolean. If you have written code in other scripting languages such as ActionScript, Python, and Ruby, you will find the concepts in this recipe easy to understand.

How to do it...

JavaFX provides two ways of declaring variables including the def and the var keywords.

def X_STEP = 50;
prntln (X_STEP);
X_STEP++; // causes error
var x : Number;
x = 100;
...
x = x + X_LOC;

How it works...

In JavaFX, there are two ways of declaring a variable:

  • def—The def keyword is used to declare and assign constant values. Once a variable is declared with the def keyword and assigned a value, it is not allowed be reassigned a new value.
  • var—The var keyword declares variables which are able to be updated at any point after their declaration.

There's more...

All variables must have an associated type. The type can be declared explicitly or be automatically coerced by the compiler. Unlike Java (similar to ActionScript and Scala), the type of the variable follows the variable's name separated by a colon.

var location:String;

Explicit type declaration

The following code specifies the type (class) that the variable will receive at runtime:


var location:String;
location = "New York";

The compiler also supports a short-hand notation that combines declaration and initialization.

var location:String = "New York";

Implicit coercion

In this format, the type is left out of the declaration. The compiler automatically converts the variable to the proper type based on the assignment.

var location;
location = "New York";

Variable location will automatically receive a type of String during compilation because the first assignment is a string literal.

Or, the short-hand version:

var location = "New York";

JavaFX types

Similar to other languages, JavaFX supports a complete set of primitive types as listed:

  • :String—this type represents a collection of characters contained within within quotes (double or single, see following). Unlike Java, the default value for String is empty ("").
  • "The quick brown fox jumps over the lazy dog" or
    'The quick brown fox jumps over the lazy dog'

  • :Number—this is a numeric type that represents all numbers with decimal points. It is backed by the 64-bit double precision floating point Java type. The default value of Number is 0.0.

    0.01234
    100.0
    1.24e12

  • :Integer—this is a numeric type that represents all integral numbers. It is backed by the 32-bit integer Java type. The default value of an Integer is 0.

    -44
    7
    0
    0xFF

  • :Boolean—as the name implies, this type represents the binary value of either true or false.
  • :Duration—this type represent a unit of time. You will encounter its use heavily in animation and other instances where temporal values are needed. The supported units include ms, s, m, and h for millisecond, second, minute, and hour respectively.

    12ms
    4s
    12h
    0.5m

  • :Void—this type indicates that an expression or a function returns no value. Literal representation of Void is null.

Variable scope

Variables can have three distinct scopes, which implicitly indicates the access level of the variable when it is being used.

Script level

Script variables are defined at any point within the JavaFX script file outside of any code block (including class definition). When a script-level variable is declared, by default it is globally visible within the script and is not accessible from outside the script (without additional access modifiers).

Instance level

A variable that is defined at the top-level of a class is referred to as an instance variable. An instance level is visible within the class by the class members and can be accessed by creating an instance of the class.

Local level

The least visible scope are local variables. They are declared within code blocks such as functions. They are visible only to members within the block.

JavaFX 1.2 Application Development Cookbook Over 60 recipes to create rich Internet applications with many exciting features
Published: August 2010
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

Read more about this book

(For more resources on JavaFX, see here.)

See also

  • Creating and using JavaFX classes
  • Creating and using JavaFX functions

Using binding and triggers to update variables

Languages, such as JavaFX, which target a visual domain have to be event-based in order to handle the non-linearity of GUI interactions. Traditionally, in a visual programming paradigm, events are generated by components when their internal states are updated. This can require an elaborate notification-handler syntax to properly express the relationship between event broadcasters and handlers.

This section explores the easy and intuitive declarative syntax of JavaFX's event-based programming. It looks at how variable values can remain synchronized using a mechanism called binding.

Getting ready

This section discusses concepts that require familiarity with variable bindings as found in other scripting languages. Binding usually refers to the ability to automatically react and handle events caused by resources (or other events) to which handlers are bound.

How to do it...

JavaFX facilitates variable binding using the bind keyword. Let us look at a simple example that shows the ease with which you can bind variables. Note that you can find listings for binding examples at ch01/source-code/src/binding/.

var step = 100;
def locX = bind step;

println ("locX = {locX}");

step = 110;
println ("locX = {locX}");

step = 150;
println ("locX = {locX}");

When you run the application, you will get the following output:

locX = 100
locX = 110
locX = 150

Notice that the value of variable locX is synchronized with the value of variable step. Whenever step is updated, locX changes in value automatically.

How it works...

The general syntax for binding looks like the following:

def variableX = bind expression

The idea behind binding is to keep variableX, on the left-hand side of the assignment, updated whenever there is a change in the bound expression on the right-hand side. JavaFX supports several forms of expressions which can be used to update the variable on the left-hand side.

Binding to variables

This is the simplest form of the binding syntax where the variable on the left is bound to other variables.

var x = 100;
def y = bind x + 10;

When the value of variable x changes, y is updated with the new value of x + 10.

Binding to a conditional

JavaFX also supports conditional binding expressions, which update the left-hand side of the assignment based on a predefined condition.

var x = 2;
def row = bind if((x mod 2) == 0) "even" else "odd";

for(n in [0..5]){
x = n;
println ("Row {n} is {row}");
}

The value of variable row is updated depending on the evaluation of the bound conditional expression.

Row 0 is even
Row 1 is odd
Row 2 is even
Row 3 is odd

In the example, when the if statement evaluates to true, row is assigned "even", else it receives "odd".

Binding to a code block

The code block binding lets developers create compound expressions to logically control how the declared variable is updated.

var x = 2;
def xDoubled = bind {
var y = 2;
y * x;
}
x = 3;
println ( "X = 3, doubled = {xDoubled}");
x = 27;
println ( "x = 27, doubled = {xDoubled}");

When x is updated, the code block is re-evaluated, and xDoubled is updated with the new value of the last expression in the block.

Be aware that assigning a code block to a variable without the bind keyword is legal in JavaFX. So, make sure not to leave the bind keyword out, as omitting it changes the meaning of the assignment, and it will behave differently.

Binding to a function

JavaFX can bind a variable to a function call as well.

function squareIt(x):Number {
x*x;
}
var param = 0;
def squared = bind squareIt(param);
param = 96;
println ("Param = {param}, squared = {squared}");

When the parameter of the function (value assigned to param) call is updated, the function is automatically re-invoked and the variable squared receives the newly calculated value.

Bind to an object literal

A variable can bind to an object literal declaration. When the values of the bound object properties change, the expression is updated with a new object.

class Location {
var x:Integer;
var y:Integer;
}
var xLoc = 0;
var yLoc = 0;
def loc = bind Location {
x: xLoc;
y: yLoc;
}
xLoc = 12;
yLoc = 234;
println ("loc.x = {loc.x}, loc.y = {loc.y}");

To avoid creating a new object every time a bound property value is updated, bind each literal property in the object declaration separately as shown.

var xLoc = 0;
var yLoc = 0;
def loc = Location {
x: bind xLoc;
y: bind yLoc;
}

There's more...

JavaFX offers another event-based mechanism called a trigger. A trigger is a code block that gets executed when the variable it is assigned to is updated. At its simplest form, a trigger is declared as follows:

def variable = value on replace [oldValueVarName]{
// code to execute
}

Here, the code block is executed when the variable on the left-hand side of the assignment is updated. The oldValueVarName variable name is optional and holds the value of variable before the update.

Using triggers

The following is a simple trigger example. You can see the full code listing for this code atch01/source-code/src/binding/TriggerDemo.fx.

def X_BOUND = 10;
var locX = 7 on replace oldX {
if(locX <= X_BOUND) {
println ("{oldX} ==> {locX}, in bound");
}else{
println ("{oldX} ==> {locX}, Out of bound!");
}
}
locX = 12;
locX = 4;

Whenever the value of variable locX is updated (including the initial assignment), the on replace trigger is executed as well.

0 ==> 7, in bound
7 ==> 12, out of bound!
12 ==> 4, in bound

See also

  • Declaring and using variables in JavaFX

Creating and using JavaFX functions

One of the types supported by JavaFX is named a function type. To be clear, this is not the type of the returned value of the function, but rather an actual data type that represents a function. This versatility throws JavaFX squarely in the realm of functional programming, where functions are regarded as first-order data types and can be manipulated just like any other supported data types. This section shows you how to create functions in JavaFX and use them as expressions in your code.

Getting ready

The concepts presented here discuss functions as an executable code unit that can be assigned and reused. You are expected to know the general purpose of a function and how to use it. If you have written any code before, you most likely know how to create and use a function.

How to do it...

In JavaFX, A function is a specialized code block preceded by the function keyword. It can accept zero or more typed parameters and always returns a typed value. Here is the declaration of a function type assigned to variable called squareIt, which returns the squared value of the number passed in as parameter. Complete code listing can be found at ch01/source-code/src/javafx/SimpleFunction.fx.

var squareIt : function(:Number):Number;
squareIt = function (x) {
x * x;
}
var square3 = squareIt(3);
println ("3 squared = {square3}");

How it works...

In JavaFX, a function has a distinct, definable type (similar to String, Number, and Integer). A function type is defined by its parameter signature and its return type. Variables (and parameters) can be assigned a function type. For instance, in the previous snippet, variable squareIt is declared as being a function type. This means that the variable squareIt can be assigned a function that takes one parameter of type Number and returns a value of type Number. squareIt can be used anywhere a function call can be used, as shown in the call var square3 = squareIt(3).

Note that the declaration and definition of the function can be combined in one step, as show next:

function squareIt(x:Number):Number{
x * x;
}

The JavaFX compiler can infer the types associated with a function's parameter signature and return value. Therefore, the function definition can be reduced to:

function squareIt(x) {
x*x;
}

The type inference engine in JavaFX will determine the proper type of the parameter based on value of the parameter at runtime. The return type of the function is based on the type of the last statement in the function or the type of the value used in the return statement.

There's more...

There are couple more features about functions in which you may be interested.

Bound functions

Since a function is a considered to be an expression in JavaFX, it can be bound to a variable (similar to a code block binding, see Using Binding and Triggers to Update Variables).

var f = 10;
bound function increaseIt(a:Number):Number {
a + f;
}
var x = 5;
def y = bind increaseIt(x);

When a function is defined as being bound, any change to values inside the function block (including its parameters) will cause an update to the binding variable. Here, whenever variable f or x changes, the value of y is updated automatically.

The run() function

JavaFX offers a way to define a script file's main entry point using the special script-level function run(). If you place the following in a script file:

function run() {
println ("I am always called!");
}

When you execute the script, the run() function will be executed as the starting point of the script by the JavaFX runtime. This similar to having the public static void main(String[] args) method in Java.

When you create a script file with script-level code without run(), the compiler creates one for you and places your script's code inside of it. As such, your script seems to execute top to bottom. However, when you provide your own run(), that is no longer the case. The JavaFX runtime will only call whatever code is inside of the run() function.

See also

  • Creating and using JavaFX classes
  • Declaring and using variables in JavaFX
  • Using binding and triggers to update variables

Integrating your JavaFX code with Java

JavaFX is built directly on top of the Java Virtual Machine (JVM). Therefore, your JavaFX code has access to the entire Java ecosystem including all of the standard Java libraries such as IO, JDBC, XML, Swing, and so on. Any compiled Java code accessible on the class path can be called from within a JavaFX script. This recipe covers the techniques required to integrate JavaFX and Java code together.

Getting ready

This section explore integration techniques between JavaFX and Java. You should have familiarity with the Java language, its libraries, or have the ability to create your own classes or libraries to be called from JavaFX.

How to do it...

The easiest way to see Java and JavaFX interoperate is to create an instance of a Java object and invoke a method on the instance from within JavaFX. Let's go through an example. You can see the full code listing in package ch01/source-code/src/java.

First create and compile this simple class:

public class JavaObject {
private String name;
public JavaObject(String n){
name = n;
}
public void printReverse() {
for(int i = name.length()-1; i >= 0; i--){
System.out.print (name.charAt(i));
}
System.out.println();
}
}

Now create a JavaFX script which creates an instance of JavaObject and invoke the the printReverse() method on the class.

var javaObject = new JavaObject("Hello World!");
javaObject.printReverse();

How it works...

Java classes and JavaFX classes are binary-compatible. When you compile your JavaFX classes, the JavaFX compiler creates a Java class file (a .class extension file). There are three points that should be made regarding the code snippet in this recipe:

  1. Similar to Java, JavaFX script supports the new operator when creating a new object instance. This makes it easy to instantiate objects written in Java from within JavaFX.
  2. While JavaFX objects can be instantiated using Object Literal Notation and the new operator, Java objects can only be instantiated with the new operator.

  3. The type inference engine will automatically determine the type of the assignment using the Java object's type.
  4. Once you have access to the Java object instance, you may invoke any public members on that object.

There is more...

In JavaFX, not only can you instantiate pure Java classes, you can also implement Java interfaces directly. Using this mechanism, you can achieve two-way integration between Java and JavaFX. Again, the full listing of the code presented here can be found in package ch01/source-code/src/java.

Implementing a Java interface in JavaFX

The steps required to implement a Java interface in JavaFX are simple. You first create a JavaFX class which extends the interface. Then, you provide JavaFX functions which implement methods defined in the interface, as given the following Java interface:

interface JavaInterface {
int add(int num1, int num2);
}

You can create JavaFX script with the following implementation:

public class JavaInterfaceImpl extends JavaInterface {
override function add(num1, num2) {
num1 + num2;
}
}
public function run() {
var adder = JavaInterfaceImpl { }
println(adder.add(1, 2));
}

Note that in JavaFX, the extends keyword is used to implement the interface instead of implements as in Java.

Note that there are other ways to achieve integration between Java and JavaFX. The rules vary depending on the level of integration you are seeking:

  1. Type integration—using Java types from JavaFX, as shown in this recipe.
  2. Framework integration—for example, calling Swing components from JavaFX.
  3. API integration—wrapping native Java libraries within JavaFX classes to expose them as JavaFX components.
JavaFX 1.2 Application Development Cookbook Over 60 recipes to create rich Internet applications with many exciting features
Published: August 2010
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

Read more about this book

(For more resources on JavaFX, see here.)

See also

  • Creating and using JavaFX classes
  • Declaring and using variables in JavaFX

Creating and using JavaFX sequences

JavaFX sequences can be described as being analogous to arrays in other languages. Imagine that you want to keep track of a group of items of the same type (say a list of numbers, for instance). You can use a sequence to store that list of items and manipulate the list with operations such as insert, query, and item removal. This section looks at how to create and work with JavaFX sequences.

Getting ready

You should be familiar with the concepts of array, list, and map data types. These are common types found in all popular languages. They are designed to function as a container of other values of arbitrary types.

How to do it...

A sequence type is declared using a non-sequence type followed the square brackets "[ ]". Below are some literal declarations of sequences. You can get full listing of the code from ch01/source-code/src/javafx/SequenceType.fx and Sequence.fx.

var numbers:Number[] = [10.0,5.6,12.3,0.44];
var numbers2 = [0,2,3,4,5,6,7,8];
var notes:String[] = ["Avion","Airplane"];
var timespans = [5s,3m,100s,5m];
var misc = [2,4.0,"messages", 5m];

How it works...

Sequence types represent a collection of other types in JavaFX. Sequences provide a flat (depth of one) container where you store references to other objects. A sequence is a first-class type in JavaFX. Therefore, it has a return type and can participate in expressions.

JavaFX supports a initialization of sequence types using literal declaration which provides a more natural way of representing the sequence. The literal expression for the sequence shows each item in the sequence separated by a comma as shown below:

var numbers:Number[] = [10.0,5.6,12.3,0.44];

The type inference engine will attempt to determine the type of the sequence variable based on the types of the items within the square brackets.

If all items within the bracket of the literal declaration are of the same type, the variable is coerced into a sequence of that type. For instance, the following example, variable numbers2 is of type Integer[]:

var numbers2 = [0,2,3,4,5,6,7,8];

If items within the brackets are of different types, the inference engine will coerce the variable to be of type Object[]. In the following code snippet, variable misc will be of type Object[] and can receive member of any type:

var misc = [2,4.0,"messages", 5m];

Similar to Java arrays, items in a sequence are referenced using a zero-based positional index. Sequence items are stored in order they are added (or declared) as shown in the snippet below from ch01/source-code/src/javafx/Sequence.fx.

var q1 = ["Jan", "Feb", "Mar"];
println (q1[0]);
println (q1[1]);
println (q1[2]);

There is more...

Sequences come with several other important features worth mentioning here. Although the literal representations of sequences looks like an array, that is where the similarity ends. Sequences support several data management operations such as insert, union, query, and delete. As you will see below, sequence expressions can also be used as generators in JavaFX loops. The code samples are from script file ch01/source-code/src/javafx/Sequence.fx.

Sequence operators

JavaFX sequences support several operators:

  • sizeof—operators return the size when applied to a sequence.
  • sizeof [1,2,3,4];

  • Comparison—JavaFX sequences can be tested for deep equality. This means that two sequences are the same if they are of the same size and contain the same items. The statement below will print true
  • println([1,2,3,4] == [4,3,2,1])

  • Reverse—this operator automatically reverses the order in which items are referenced in a sequence.

    println(reverse ["Jan", "Feb", "Mar", "Apr");

Sequence operations

JavaFX sequences also support operations to manipulate sequences and sequence items directly.

  • Insert Operation—as the name implies, this operation inserts item(s) into a given sequence. The following example shows all of the supported form of insert.
  • var months = ["Jan"];
    insert "May" into months;
    insert ["Mar","Apr"] before months[1];
    insert "Feb" after months[0];

    Besides the into directive, note that the insert operation support a before and after clause which specifies the location (index) where the item is to be inserted.

  • Union—sequences can be nested using literal declaration to create new lists:
  • var q1 = ["Jan", "Feb", "Mar"];
    var h1 = [q1, ["Apr", "May", "Jun"]];

  • Delete Operation—the delete operation removes items from a given sequence. The following example shows the supported forms of delete.
  • var months = ["Jan", "Feb", "Mar", "Apr", "May"];
    delete "May" from months;
    delete months[3];

It is critical to understand that sequences are immutable, meaning that the values in a sequence do not change. Rather, any modification to a sequence (insert, delete, and so on) generates a new sequence object to reflect the modification desired.
When deleting by value (that is, delete "May" from months), all items of same value will be removed from the sequence.

Sequence slices

Sequence slice notations are used to generate subsets of larger sequences. Given this sequence

var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"];

Here are some slice operations supported by JavaFX:

  • months[1..4]—returns a sequence ["Feb", "Mar", "Apr", "May"]
  • months[0..<3]—returns sequence [ "Jan", "Feb", "Mar"]
  • months[3..]—returns sequence ["Apr", "May", "Jun"]
  • months[0..<]—returns sequence ["Jan", "Feb", "Mar", "Apr", "May"]

Sequence Projection—you can use constraint expressions to project sub-sequences on a given sequence using format sequence[x | {Boolean expression}]. This notation reads as "select all element x where the Boolean expression is true".

:
months[m|m.startsWith("M")]

The above code returns sequence ["Mar", "May"] from var months declared previously. This expression creates slices based on given arbitrary Boolean condition. It reads as "for all item m in months where m starts with M."

Sequence loop query

The loop structure is used to query elements in sequences to create subsets based on conditional expressions. The general format is:

for (x0 in seq0 [where {Boolean expression}][, queryn]){}

The loop expression can use a where clause along with a Boolean expression to filter down to specific elements to build the subset. A simple example is:

var points = [1,2,3,4,5,6,7,8,9,10,11,12,13,14];
var evenPoints = for(n in points where n mod 2 == 0) {n}
println (evenPoints);

In the previous code, the loop generates a new sequence with only even members from the original sequence, [ 2, 4, 6, 8, 10, 12, 14 ], using the where clause to specify a selection expression.

Also notice you can add more than one query in the loop expression where the result is a Cartesian product of all subsets expressed in each query. For instance, the following will produce 14 elements

var doublePoints = for(n in points where n mod 2 == 0,
i in [2,4]){
n * i
}
println (doublePoints);

This code loops over two sequences; the first sequence contains all even members of the original points variable declared previously; the other is a two-member sequence containing 2 and 4, the loop generates new sequence [ 4, 8, 8, 16, 12, 24, 16, 32, 20, 40, 24, 48, 28, 56 ].

Working with JavaFX String

String is a fundamental value type in JavaFX. Similar to Java and other languages on the JVM, the String type is used to represent text literals within a single or double quotes. Unlike Java, however, JavaFX strings have additional capabilities which will be explored in this section.

Getting ready

You should be familiar with the notion of string literals and expressions.

How to do it...

We have already seen how to use String types in other recipes. When creating a String, you simply create a literal or expression to represent the string's content, and use the curly braces to embed expressions as shown below. The full listing for this code can be found in ch01/source-code/src/javafx/StringDemo.fx.

var str1:String = "Hello World!";
var str2 = "Goodbye forever";
var title = "King";
println ("The {title} has arrived!");

var evens = [0, 2, 4, 6, 8];
println("What are the odds {for(d in evens) "{d + 1} "}");

var amount = 445234.66;
println ("Your house is worth ${%,.2f amount}");

How it works...

Similar to other types, a string can be declared with a literal representation, participate in expressions, and hold a value. The previous snippet shows the literal declaration of a string. Variable str2 is coerced by the type-inference engine into a String type implicitly.

One of the interesting features of the String type in JavaFX is its ability to have embedded expressions (similar to other templating languages) enclosed in curly braces. In the previous code snippet, println ("The {title} has arrived!") will print the string with the value of the variable title embedded in it.

You can also have complex expressions embedded in the string, as is shown from the code snippet println("What are the odds {for(d in evens) "{d + 1} "}") from the recipe. The embedded expression contains a loop that traverses elements from variable evens and outputs the result from the nested string "{d + 1}" with each pass, producing new string What are the odds 1 3 5 7 9.

The JavaFX Sting type has the ability to process string formatting expressions based on Java's java.util.Formatter class. In the previous code snippet, we used format expression %,.2f to format the variable amount which displays Your house is worth $445,234.66. You can find information about supported format expressions at http://java.sun.com/javase/6/docs/api/java/util/Formatter.html.

There is more...

Before we leave the discussion on String, it's worth taking a look at localization. In JavaFX, the localization mechanism is an extension of the string expression.

Using JavaFX localization

To mark a String literal as a localized string, simply prefix the string with double hashes. This causes JavaFX to substitute the string with a localized string, if one is found, from a locale properties file.

To illustrate, let's look at an example. The code for this example is found in package ch01/source-code/src/locale.

Create a JavaFX script file with the following content:

var msg1 = ##"Lift the cover";
var msg2 = ##[red button]"Press the red button to destroy";
println (msg1);
println (msg2);

Save the file as Localization.fx and compile. Now, create a text file named Localization_fr.fxproperties and type in the following:

"Lift the cover"="Soulevez le couvercle"
"red button"="Appuyez sur le bouton rouge pour détruire"

Notice that JavaFX can use either the actual string or a string key (red button) to do the substitution for the localized string. When the code is compiled and executed, the output is:

Soulevez le couvercle
Appuyez sur le bouton rouge pour détruire

The strings are substituted automatically by the JavaFX runtime with their French translation. If no properties file is found for the locale, JavaFX defaults to the actual String assigned to the variable.

Summary

In the above aricle we have covered:

  • Using javafxc to compile JavaFX Code
  • Creating and using JavaFX classes
  • Creating and using variables in JavaFX
  • Using binding and triggers to update variables
  • Creating and using JavaFX functions
  • Integrating your JavaFX code with Java
  • Creating and using JavaFX sequences
  • Working with JavaFX string

Further resources on this subject:


About the Author :


Vladimir Vivien

Vladimir Vivien is a software engineer living in the United States. Past and current experiences include development in Java and .Net for industries including publishing, financial, and healthcare where he worked with a number of varied technologies including user-facing GUI frontends and backend mid-tiers. Vladimir enjoys taking part in open source projects and has contributed JmxBuilder to the Groovy project and is an author of other projects such as JmxLogger. Beside JavaFX, he has a wide range of technology interests including Java, OSGi, Scala, and anything else that runs on the JVM.

Books From Packt


NetBeans Platform 6.9 Developer's Guide
NetBeans Platform 6.9 Developer's Guide

MooTools 1.2 Beginner's Guide
MooTools 1.2 Beginner's Guide

YUI 2.8: Learning the Library
YUI 2.8: Learning the Library

Learning Ext JS 3.2
Learning Ext JS 3.2

Java EE 6 with GlassFish 3 Application Server
Java EE 6 with GlassFish 3 Application Server

Tomcat 6 Developer's Guide
Tomcat 6 Developer's Guide

Spring Persistence with Hibernate
Spring Persistence with Hibernate

EJB 3.0 Database Persistence with Oracle Fusion Middleware 11g
EJB 3.0 Database Persistence with Oracle Fusion Middleware 11g


Your rating: None Average: 5 (1 vote)

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
C
x
m
L
e
m
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software