Home Java JavaFX from the inside

JavaFX from the inside

by admin

At JavaOne 2011 the final version of JavaFX 2.0 was announced.Let’s see what it consists of and what tools it offers.
JavaFX from the inside

Hello JavaFX

Let’s create and run our first JavaFX application.To do this we need JavaFX 2.0 SDK and latest Netbeans You can read about setting up JavaFX in Netbeans at http://netbeans.org/kb/docs/java/javafx-setup.html
Start Netbeans, choose File/New Project from the menu, select the JavaFX category and the JavaFX Application project type in the dialog box. This will create a project with one test form (you can name the project HelloJavaFX or something else).The code of the form class :

package hellojavafx;import javafx.application.*;import javafx.event.*;import javafx.scene.*;import javafx.scene.control.*;import javafx.stage.*;public class HelloJavaFX extends Application {public static void main(String[] args) {Application.launch(args);}@Override public void start(Stage primaryStage) {primaryStage.setTitle("Hello World");Group root = new Group();Scene scene = new Scene(root, 300, 250);Button btn = new Button();btn.setLayoutX(100);btn.setLayoutY(80);btn.setText("Hello World");btn.setOnAction(new EventHandler<ActionEvent> () {public void handle(ActionEvent event) {System.out.println("Hello World");}});root.getChildren().add(btn);primaryStage.setScene(scene);primaryStage.show();}}

result :
JavaFX from the inside
Let’s see what appears in the dist folder after compiling. The following files will be there :
– The folder web-files contains images to run as an applet
– HelloJavaFX.html – page with the built-in applet
– HelloJavaFX.jar – application for launching with a normal double mouse click
– HelloJavaFX.jnlp – descriptor of startup via WebStart
We are interested in HelloJavaFX.jar application itself. Let’s open it with any archiver (.jar is a normal .zip archive) and look at the manifest. The main startup line is :
Main-Class: com/javafx/main/Main
tells Netbeans to add a com.javafx.main.Main starter class to every JavaFX application, which initializes all JavaFX libraries and starts the application itself. The name of the main class is taken from the JavaFX-Application-Class field, in our case it is hellojavafx.HelloJavaFX
Nothing out of the ordinary. At the moment, JavaFX is just a set of libraries whose functions can be used from Java code.

JavaFX in Swing

Let’s look at an example of a Swing form with an embedded JavaFX component. Create a new project in Netbeans and add reference to JavaFX Runtime library (by default it is located in C:\Program Files\Oracle\JavaFX Runtime 2.0\lib\jfxrt.jar).
Once Runtime is connected, you can embed any JavaFX components using the JFXPanel Let’s add a text editor using the following code :

package swingjavafx;import javax.swing.*;import java.awt.event.*;import javafx.embed.swing.*;import javafx.scene.*;import javafx.application.*;import javafx.scene.web.*;import javafx.scene.effect.*;public class SwingJavaFx extends JFrame {HTMLEditor edtr;public SwingJavaFx() {this.setSize(600, 400);this.setVisible(true);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setLayout(null);JButton b1 = new JButton("Read");b1.setSize(150, 22);b1.setLocation(10, 10);b1.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {JOptionPane.showMessageDialog(null, edtr.getHtmlText());}});this.add(b1);final JFXPanel jfx = new JFXPanel();jfx.setSize(560, 300);jfx.setLocation(10, 40);this.add(jfx);Platform.runLater(new Runnable() {@Override public void run() {Group root = new Group();Scene scene = new Scene(root, 400, 300);jfx.setScene(scene);javafx.scene.shape.Rectangle rctngl = new javafx.scene.shape.Rectangle();rctngl.setTranslateX(20);rctngl.setTranslateY(30);rctngl.setWidth(500);rctngl.setHeight(250);rctngl.setEffect(new Shadow());root.getChildren().add(rctngl);edtr = new HTMLEditor();edtr.setHtmlText("Blablabla");edtr.setTranslateX(20);edtr.setTranslateY(30);edtr.setPrefWidth(500);edtr.setPrefHeight(250);root.getChildren().add(edtr);}});}public static void main(String[] args) {new SwingJavaFx();}}

The result is this form :
JavaFX from the inside
As you can see from the code of the Read button, we can access the data in the text editor at any time. To run such an application we have to add to the class-path the path to the JavaFX Runtime-library, for example this :
java -cp %cp%;"C:\Program Files\Oracle\JavaFX Runtime 2.0\lib\jfxrt.jar";SwingJavaFx.jar swingjavafx.SwingJavaFx
It’s quite trivial and no different from using other libraries in Java projects.

API JavaFX

JavaFX features can be found at platform page The API has a set of classes for drawing primitives, graphs, a set of GUI components with their own design. Finally there is a web browser component and a text editor with formatting capabilities.
On the page http://www.oracle.com/technetwork/java/javafx/overview/index.html you can run the demo application Ensemble (which is analogous to the Flex Component Explorer ).
JavaFX from the inside

Binding

Binding is for linking object properties. For example, you can bind the coordinates of a button to the width of a window and as a result, when you change the size of a form, the bound button will move too.
Let’s take the example of :

package bindingjavafx;import javafx.application.*;import javafx.event.*;import javafx.scene.*;import javafx.scene.control.*;import javafx.stage.*;import javafx.beans.binding.*;import javafx.beans.value.*;public class BindingJavaFX extends Application {public static void main(String[] args) {Application.launch(args);}@Override public void start(Stage primaryStage) {primaryStage.setTitle("Hello World");Group root = new Group();final Scene scene = new Scene(root, 300, 250);final Button btn = new Button();btn.setLayoutX(100);btn.setLayoutY(80);btn.setText("Hello World");btn.setOnAction(new EventHandler<ActionEvent> () {public void handle(ActionEvent event) {System.out.println("Hello World");}});final DoubleBinding db = scene.widthProperty().subtract(150);db.addListener(new javafx.beans.value.ChangeListener< Number> () {public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) {btn.setLayoutX(db.getValue());}});root.getChildren().add(btn);primaryStage.setScene(scene);primaryStage.show();}}

Result :
JavaFX from the inside
Code line
final DoubleBinding db = scene.widthProperty().subtract(150);
creates a variable db and binds its value to the width of the form minus 150 pixels. Unfortunately, we can’t just bind the button coordinates to this variable (like btn.layoutX.bind(db); that would be obvious and convenient). That’s why we need to add a Listener to the created variable, where we can update the coordinates of the button:

db.addListener(new javafx.beans.value.ChangeListener< Number> () {public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) {btn.setLayoutX(db.getValue());}});

In addition, binding introduces additional restrictions – if you bind a property to a variable you can’t change it by simple assignment, an exception will be thrown at runtime of the application.
The API code itself is excessively bloated, e.g. class SimpleDoubleProperty has an inheritance hierarchy of six classes and implements nine interfaces. This is a new understanding of the simple characteristic.
The result is that a good idea doesn’t look very attractive. A lot of code, implicit errors. Although simple and straightforward linking implementations are available for many languages and libraries, including for Swing

Using CSS

The appearance of the interface can be defined with CSS. To do this, you need to create a stylesheet, for example this :

cssbutton {-fx-font: 16px "Serif";-fx-padding: 10;-fx-background-color: #CCFF99;-fx-effect: dropshadow( one-pass-box , black , 12 , 0.0 , 1 , 1 );}

– The cssbutton style sets the font, indentation, fill and shadow effect. Next, you need to attach the styles file to the scene :
scene.getStylesheets().add("cssjavafx/style.css");
and add a style to the component named :
btn.getStyleClass().add("cssbutton");
The button will look something like this :
JavaFX from the inside
For a description of the properties available in CSS, see on the documentation page
I don’t really understand why you need to set styling at all. Everything you can set with styles can be done in code, you can’t use variables or calculations in CSS, you can’t create new properties, styles are hard to debug.

Using FXML

The layout of the forms can be defined in a separate FXML file and loaded from it when the application starts. This approach is used in many development environments.
In Netbeans, you can create a project with type JavaFX FXML Application for this purpose. An initial form will be created with the following content :

package fxmljavafx;import java.net.*;import java.util.*;import javafx.event.*;import javafx.fxml.*;import javafx.scene.control.*;public class Sample implements Initializable {@FXML private Label label;@FXML private void handleButtonAction(ActionEvent event) {System.out.println("You clicked me!");label.setText("Hello World!");}@Override public void initialize(URL url, ResourceBundle rb) {//}}

The @FXML annotation is used to indicate variables and functions available when loading from an FXML file. The file itself looks like this :

<?xml version="1.0" encoding="UTF-8"?><?import java.lang.*?><?import javafx.scene.*?><?import javafx.scene.control.*?><?import javafx.scene.layout.*?><AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml" fx:controller="fxmljavafx.Sample"><children><Button id="button" layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" /><Label id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" prefHeight="16" prefWidth="69" fx:id="label" /></children></AnchorPane>

As you can see in the example, both the handleButtonAction method and the label property specified in the code are used within the FXML description of the form.
Loading the FXML form when the application starts is called like this :

Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));stage.setScene(new Scene(root));stage.show();

There’s no advantage in creating such a GUI.There’s no visual editor, and it’s equally expensive to hand edit both the Java code and the FXML description.

Visual editor

There is a form editor in Visual Studio for VB and C#, in Adobe Flex, in Oracle JBuilder there is an excellent editor for Swing. For JavaFX the visual editor was announced 2 years ago. You can even watch a video of it on http://www.flickr.com/photos/douglasbullard/3609213630/in/photostream/
But so far there has been no public release and no one knows when it will be.

A dollop of honey in a barrel of tar

The overall rating is most likely unsatisfactory. Demo applications are slow, components look inferior to Macintosh Aqua, Adone Flex or Microsoft Metro. First version of JavaFX appeared in 2008, but Sun never managed to make it up to date.
Nevertheless, at the last JavaOne there was a lot of talk about JavaFX. Let’s hope that Oracle with an iron hand will lead the developers in the right direction and make them finally deliver a working tool instead of promises.

You may also like