Application and Lesson by Vijesh Aaniyamveetil
Introduction

JavaFX is a new expressive scripting language from SUN for the RCP/RIA world and competes directly with FLEX, Silverlight etc. Instead of enhancing the existing RCP module Swing and carrying along the burden of preserving backward compatibility, the engineers of Java had decided to come up with new language that is compatible with and leverages the robustness of existing Java language.

Though with the current release the JavaFX team concentrated on mainly graphic and video support rather than emulating Swing component sets, there are some limited built-in components for data centric applications. Besides it is also possible to use core Swing components within context of JavaFX application. In the future releases of JavaFX, first class components that are not available now (likes of JTable, JTree etc.), will be included.

In this example a mix of JavaFX and Swing components are used to demonstrate the integration between them. The data layer and number of pages are same as that of other samples in this site.

Since I am also new to JavaFX, the utilization of the JavaFX features may not very effective and there is room for improvement. I myself will try to improve it as I learn more about the language and you are also welcome to suggest improvements.

Prerequisites

Java SE Development Kit (JDK): JDK 6 Update 7 minimum (JDK 6 Update 11 recommended)

NetBeans 6.5:  http://www.netbeans.org/

JavaFX SDK 1.1: http://www.javafx.com/downloads/all.jsp

Basic JavaFX language knowledge:  http://www.javafx.com/learn/

Java Swing knowledge:  http://java.sun.com/docs/books/tutorial/uiswing/

Operating systems: Microsoft Windows XP with Service Pack 3 or Windows Vista, Macintosh OS X 10.4.10 minimum

About the sample application

This example is a JavaFX implementation of Employee CRUD model used in all the other examples in this site. The features available are:
  1. Display the list of employees
  2. Create new employees
  3. Edit existing employee details
  4. Delete existing employee
  5. Change the background image at runtime
 
Client Layer
MainFrame.fx
All the application specific JavaFX coding
ImageButton.fx
Image Hovering class from a javafx.com sample
TableHelper.java
All the Swing JTable related coding is placed here
 
Service Layer
It is a copy of the classes available in Wicket CRUD example. Reference to Logger class is removed to reduce the overall size.
Code Explanation

Variable Declaration

The first two set of declarations are related to window size and position. The keyword “def” is used to represent constant values and is similar to “final” keyword is java. The keyword “var” represents generic dynamic variable.

The distinction between these two types is clear from their usage: window size doesn’t change in the example but its position can be changed.


// Application Width and Height

def stageWidth = 600;

def stageHeight = 450;

// initial window location

var stageX:Number = 320;

var stagey:Number = 160;

// Is running as Applet in browser? If no, show close [X] button

var inBrowser="true".equals(FX.getArgument("isApplet") as String);

var currentEmployee:Employee = null;

See the usage of “: Employee”. This is how type of variable is declared in JavaFX.


Transparent taskbar

The standard application taskbar is not displayed, yet it can be dragged around by holding the mouse at the top area of the window.  It is made possible by a transparent Rectangle.

var titleBar = Rectangle {

    width:stageWidth

    height:25  // a horizontal strip with height 25 pixels

    fill: Color.TRANSPARENT

    visible: bind (not inBrowser)

    onMouseDragged: function(e) {

        stageX += e.dragX;

        stageY += e.dragY; // these two statements make the window move around

    }

}

Display of this rectangle depends on the value of the variable inBrowser, which is obtained from a parameter that indicates whether the application is running as applet or not. This is an example of data binding (through the keyword bind) feature available in JavaFX and is utilized in other parts of the example. Note that an expression can also be used with bind keyword.

See http://java.sun.com/javafx/1/tutorials/core/dataBinding/ for more details on JavaFX binding


Closing the Window

It is not necessary to program for closing the window. Since the application is in headless mode (i.e. without standard taskbar), closing of window had to be taken care of


var closeButton: ImageView = ImageButton {

    // places it at the right top corner

    x: stageWidth - 20

    y: 5

    normalImage: Image { url: "{__DIR__}images/close_n.png" }

    selectImage: Image { url: "{__DIR__}images/close_h.png" }

    visible: bind (not inBrowser)

    onMouseClicked: function(e) {

      javafx.lang.FX.exit();//closes the application programmatically

 }

}

The “closeButton” (it is an ImageView) is used to dispose the application window. Attributes x and y is used to place the button at the top right corner; this value is relative to the “root” node(Window/Stage) position.  __DIR__" points to the directory in which current .fx file is placed. The class ImageButton is taken from a javafx sample: it provides hovering effect on the button.

http://javafx.com/samples/InterestingPhotos/src/ImageButton.fx.html


Background image handling

The below code snippets takes care of displaying and shuffling background images in this application. See how easy it is to create a new object (bgImage = ImageView), no “new” keyword, and the variable type is optional. Note that a function call is made to initialize the image variable

The image files are named background0.JPG through background4.JPG. See the usage of  curly braces with variables as in {bgn} here; this is similar to using + operator with String in Java.

bgImage.image = getRandomImage(); This statement changes the background image; no additional calls like repaint() or revalidate() to make the effect!!.


var bgImage = ImageView {

    x: 2

    y: 2

    image: getRandomImage()

}

function getRandomImage() {

    var bgn = new Random().nextInt(5);

    Image {

        url: "{__DIR__}images/background{bgn}.JPG"

    }

}

var bgButton: ImageView = ImageButton {

    . . . . . some code is not shown for brevity

    onMouseClicked: function(e) {

      // simply assigning a new image changes the background no explicit repaint/refresh!!

        bgImage.image = getRandomImage();

    }

}


Creating a Button

var newEmpButton: SwingButton = SwingButton {

    text: "Add Employee"

    action: function() { // actionPerformed

        buttonText = "Create";

        onNewEmp ();

    }

}


Bringing JTable in JavaFX script

Creation of JTable, TableModel and the operations on them are encapsulated in TableHelper.java. Those who are familiar with Swing would understand the code. Explanation for the contents of this class is beyond the scope of this tutorial.


var table = TableHelper.create();

table.setPreferredSize(new Dimension(stageWidth,140));

// this is how swing component is added as a content in JavaFX node/scene

var tableComp = SwingComponent.wrap(table);

More details: http://javafx.com/samples/ExercisingSwing/index.html


Employee Details Page (Edit/Create)

The below code snippets shows how to create TextField and ComboBox in JavaFX . Notice how the ComboBox items are initialized on the fly from the list of departments. See the usage of “as” to cast the variable to a particular type.

var dept: Department = department as Department; in JavaFx

equivalent to

Department dept=(Department)department;        in Java


var firstNameField = SwingTextField {

    columns: 15

    borderless: true

};

var departments = new DepartmentNoDBdao().getAllDepartments();

// create and initialize the departments combobox

var deptComboBox = SwingComboBox {

    selectedIndex: 2 // default selected item index

    width: 100

    items: for (department in departments)

        SwingComboBoxItem {

            // "as" is used for casting in JavaFX

            var dept: Department = department as Department;

            text: dept.getName(); // display text

            value: dept; // Object associated with the text

        }

}


Edit/Create Button

editCreateButton represents the save button in employee details page that gets labeled “Edit” when “Edit Employee” button is pressed and “Create” for “Add Employee” respectively in the front page. Notice the usage of bind keyword with buttonText (button label changes when its value changes)

Also note how the selected data is fetched from the ComboBox.

“currentEmployee” is variable of type Employee that represents either the currently selected record in the table in the case of Edit or a new empty Employee object in the case of “Add”. See the functions onEditEmp () and onNewEmp ()


var editCreateButton = SwingButton {

    text: bind buttonText // Text is based on the button clicked in the front page

    action: function() {        

currentEmployee.setFirstName(firstNameField.getJTextField().getText());

        var depItem: SwingComboBoxItem = deptComboBox.getJComboBox().getSelectedItem() as SwingComboBoxItem;

        currentEmployee.setDepartment(depItem.value as Department);

        if("Create".equals(buttonText))

            new EmployeeNoDBdao().insertEmployee(currentEmployee);

        onCancel ();// done with edit/create, back to front page

        TableHelper.refresh();

    }

};


Employee Details Page: “Form Fields”

The below code snippet is used to layout fields and the associated labels in a standard alignment. Notice the usage of HBox and VBox; both are built-in layouts available in JavaFX to place components in a grid like layout.  The first one is a simple layout manager that puts all nodes in an horizontal line, one after other. And the second do the same, but in a vertical line. Here different spacing size used to adjust for the height difference in Label and Field components.

Unlike x and y which are in relative to “root” node,  translateX and translateY applies after transforming the current node with relation to the root and sibling nodes.  Use this for minor adjustments.


var newEmpFieldsBox = HBox{

    spacing: 20

    translateX: 10

    translateY: 10

    content: [

        VBox{

            spacing: 20

            content: [

                SwingLabel {

                    text: "First Name: "

                    font: labelFont

                },

                SwingLabel {

                    text: "Last Name:"

                    font: labelFont

                },

                .............

                editCreateButton

            ]

        }

        VBox{

            spacing: 17.5

            content: [firstNameField,lastNameField,ageField,deptComboBox,cancelButton]

        }

    ]

}


Switching between pages

This is surprisingly easy in JavaFX; no remove/add on a parent container, no refresh and repaint method calls. Just switching the referred Node of a bound variable does the trick.

The following code snippets show the places where page switching is done. As you can see pageHolder which is bound to a location is the key to this feature.


function onEditEmp () {       .............     // show the employee details page...     pageHolder = empDetailsPage;

}

function onNewEmp () {

    ................     // show the employee details page...     pageHolder = empDetailsPage;

}

function onCancel () {

      // done with Edit/Create show me the front page         pageHolder = frontPage;

}


Layering/Grouping Components and Nodes
The below part is the section that does “putting things together” aspect of the application.

The scenegraph used in JavaFX is a tree-like data structure where each item in the tree has zero or one parent, and each item is either a "leaf" with zero sub items or a "branch" with zero or more sub items.  The positioning of each component in a JavaFX application will be depend on its x & y coordinates, translateX & translateY transformations, spacing of layouts etc.

Let’s explain the important statements from the bottom up:

var stageContent = [bgImage,closeButton,bgButton,contentBox];

All the contents of this node get displayed based on their individual coordinates relative to its parent Stage. 

pageWrapperBox is used to bind pageHolder with it. pageHolder can not directly be bound as a element in the content  array of contentBox

pageHolder is a variable that points to currently displayed page. Assigning individual page Node to this variable will make it get displayed in the contentBox thanks to the bind magic.


var buttonNode: Node[];

buttonNode = [newEmpButton, editEmpButton,delEmpButton];

var frontPage = VBox {

    spacing: 10

    content: [buttonNode, tableComp]

};

var pageHolder = frontPage; //initial page

// used this VBox to take advantage of "bind" key word with content

var pageWrapperBox = VBox {

    spacing: 10

    content: bind pageHolder

}; 

// organizes the contents in a box and provide spacing between adjacent ccomponents

var contentBox = VBox {

    spacing: 10

    content: [titleBar,titleText,pageWrapperBox]

};

// place all the components in the Stage

var stageContent = [bgImage,closeButton,bgButton,contentBox];


Stage or “root” Node

The JavaFX Stage class is the top level container for the FX script instantiation. This is similar to the JFrame class in Swing. Note the usage of “with inverse” on the bind keyword: this is how binding is made bidirectional.  Bidirectional bind allows updates to flow in either direction, rather than just from the bound expression to the variable.


Stage {

    width: stageWidth

    height: stageHeight

    visible: true

    x: bind stageX with inverse

    y: bind stageY with inverse

    // comment the “style” to display standard task bar

    style: StageStyle.TRANSPARENT

    scene: Scene {

        content: Group {

            content: stageContent

            clip: Rectangle {

                width: stageWidth

                height: stageHeight

                arcWidth: 20

                arcHeight: 20

            }

        }

        fill: Color.WHITESMOKE

    }

}

Wrapping Up

This is a simple raw JavaFX example to demonstrate the usage of JavaFX to develop CRUD applications. The integration of Swing components into JavaFX and the contextual explanation on some of the JavaFX language concepts are also included. I do not claim it to be a perfect example as I am also new to this language but hope that it gives you a head start on developing similar applications using JavaFX. Hopefully I shall come up with an improved and more organized version of the same example in the future.

In case you wonder where the background images are from: http://images.google.com/images?hl=en&q=Kerala&gbv=2

Comments and Feedbacks

Please provide the comments and feedbacks at my blog

http://something-about-tech.blogspot.com/2009/02/javafx-crud-application.html