JavaFX

JavaFX FXGraph Example

This is a JavaFX FXGraph Example. FXGraph is a simple DSL for the definition of a JavaFX 2.x object graph. Instead of generating Java source or byte code, it generates FXML, a special XML format supported by the JavaFX 2.x library.

The language supports the following concepts:

  • JSON-like object graph notation
  • Static properties access
  • Binding Expressions
  • Controller Binding
  • Translation Support
  • Support for CSS referencing

 
The following table shows an overview of the whole article:

The following examples uses Java SE 8.

1. Installing the e(fx)clipse IDE

FXGraph is part of the e(fx)clipse IDE. So you have to install this IDE in Eclipse. If you want learn more about e(fx)clipse, please read my article JavaFX Applications with e(fx)clipse.

At first you have to start your Eclipse Software. Thereafter go to the Help Menu and select the “Install New Software…” option.

The following Dialog will appear:

The Install new Software Dialog
The Install new Software Dialog

Now you have to define a Repository for the e(fx)clipse Installation. After clicking the Add Button, the “Add Repository” Dialog will appear:

The Add Repository Dialog
The Add Repository Dialog

You have to enter the name of the repository and the Location of the software. I have chosen e(fx)clipse as name and http://download.eclipse.org/efxclipse/updates-released/2.3.0/site as Location for the following examples.

After defining the Repository, all possible items of the Update-Site will appear. Now you can choose, which items should be installed:

The Check Items Dialog
The Check Items Dialog

At the end of the Selection and pressing the Next Button, an Overview of the selected items will apppear:

The Install Details Overview
The Install Details Overview

At next, the terms of the License Agreement have to be accepted:

The Review License Dialog
The Review License Dialog

After clicking the Finish Button, the installation will start:

The Install Dialog
The Install Dialog

When the installation process is finished, you have to restart your Eclipse. Thereafter you can create JavaFX Projects with the e(fx)clipse IDE in your Eclipse Environment.

2. Your first FXGraph Example

In this example, I only discuss how you can generate the Project and the necessary changes in the created files. If you want to learn more about JavaFX, please read my JavaFX Tutorial for Beginners.

2.1 Creation of the FXGraph Project

At first you have to create a JavaFx Project. Go to the File Menu and choose New Project. Select the “JavaFX Project” entry in the wizard:

Choose the Type of the new Java Project
Choose the Type of the new Java Project

Enter a project name and click Next:

The Create Java Project Dialog in Eclipse
The Create Java Project Dialog in Eclipse

Now you can add other external libraries, if it is necessary:

The Java Settings Dialog
The Java Settings Dialog

The next step represents the Selection of the “Application Type”. There exists Desktop and Mobile. For this article I have chosen Desktop for the creation of a Desktop Application.

Selecting the Application Type of the new FXGraph Project
Selecting the Application Type of the new FXGraph Project

Now you have to choose the Language. You can select None, FXML and FxGraph. None means, that the Project contains only Java Files and StyleSheets. If you want to use FXML for developing your GUI, you have to select FXML. FXGraph is a simple DSL for the definition of a JavaFX 2.x object graph. Choose FXGraph.

Selecting the Language of the new FXGraph Project
Selecting the Language of the new FXGraph Project

Thereafter you have to choose the Root Type. The Root Type can be BorderPane, VBox, etc.

Selecting the Root-Type of the new FXGraph Project
Selecting the Root-Type of the new FXGraph Project

The next step contains the definition of the File Name and the Controller Name.

Definition of the File and Controller Name of the new FXGraph Project
Definition of the File and Controller Name of the new FXGraph Project

After a click on the Finish Button Eclipse will create the Project and some Classes and Stylesheets:

The generated FXGraph Project
The generated FXGraph Project

Thereafter, the application Package contains the following Files:

  • Main.java
  • application.css
  • BorderPaneControllerExample.java
  • BorderPaneExample.fxgraph
  • BorderPaneExample.fxml

2.2 Changing the FXGraph File

The generated File “BorderPaneExample.fxgraph” contains the following code after generation:

BorderPaneExample.fxgraph

import javafx.scene.layout.BorderPane
import application.BorderPaneControllerExample

component BorderPaneExample controlledby BorderPaneControllerExample {
	BorderPane {
		//TODO Add Nodes
	}
}

As you can see, the definition of an object graph with FXGraph looks quite similar to JSON, but because Java has the concept of a package, you can import classes from a package so that you don’t have to specify the fully qualified name.

Another difference to JSON is that the definition starts with the component keyword which typically matches the filename.

The above file creates an empty BorderPane at this time. In this example we only want to add a Button and his corresponding Text at the center of the BorderPane. The modified file contains the following code:

BorderPaneExample.fxgraph

import javafx.scene.layout.BorderPane
import javafx.scene.control.Button
import application.BorderPaneControllerExample

component BorderPaneExample controlledby BorderPaneControllerExample 
{
	BorderPane 
	{
		center : Button 
		{
      			text : "Hello World"
    		}
	}
}

The attribute and its value are separated by the “:” (colon) and the following simple values are supported directly:

  • String
  • Numbers
  • Object definition

For example, the following code snippet defines the Text for the Button:

center : Button 
{
	text : "Hello World"
}

2.3 Changing the FXML File

The File “BorderPaneExample.fxml” contains the following code after creation:

BorderPaneExample.fxml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
	Do not edit this file it is generated by e(fx)clipse from ../src/application/BorderPaneExample.fxgraph
-->

<?import java.lang.*?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="application.BorderPaneControllerExample">

</BorderPane>

The FXGraph needs to be loaded as a FXML file JavaFX Scene. The e(fx)clipse project will translate the FXGraph “BorderPaneExample.fxgraph” specification file to a “BorderPaneExample.fxml” file. After translation, the file contains the following XML Code:

BorderPaneExample.fxml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
	Do not edit this file it is generated by e(fx)clipse from ../src/application/BorderPaneExample.fxgraph
-->

<?import java.lang.*?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="application.BorderPaneControllerExample">

	<center>
		<Button text="Hello World"/> 
	</center>
</BorderPane>

In other words, we don´t have to made changes in this file.

2.4 Changing the Stylesheet

The corresponding Stylesheet is also empty after Creation:

application.css

/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */

In this example, it is not necessary to make changes in the Stylesheet.

2.5 Changing the Controller Class

The generated File “BorderPaneControllerExample.java” is also an empty class after creation. In this example, we only have defined a BorderPane with a Button and a Text. Given the fact, that there is no Action defined on the Button, we don´t need to change the Controller Class.

BorderPaneControllerExample.java

public class BorderPaneControllerExample 
{
}

2.6 Changing the Main Class

The generated Main Class contains the following Java Code after Creation:

Main.java

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXMLLoader;


public class Main extends Application 
{
	@Override
	public void start(Stage primaryStage) 
	{
		try 
		{
			BorderPane root = (BorderPane) FXMLLoader.load
				(getClass().getResource("BorderPaneExample.fxml"));
			Scene scene = new Scene(root,400,400);
			scene.getStylesheets().add
				(getClass().getResource("application.css")
				.toExternalForm());
			primaryStage.setScene(scene);
			primaryStage.show();
		} 
		catch(Exception e) 
		{
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) 
	{
		launch(args);
	}
}

At first, the FXML File will be loaded:

BorderPane root = (BorderPane) FXMLLoader.load
	(getClass().getResource("BorderPaneExample.fxml"));

Thereafter the Scene will be created and the corresponding Stylesheet will be added to the Scene:

Scene scene = new Scene(root,400,400);
scene.getStylesheets().add
	(getClass().getResource("application.css")
	.toExternalForm());

At last, the Scene will be added to the Stage and the Stage itself will be shown:

primaryStage.setScene(scene);
primaryStage.show();

In this example, I only have made two changes in the Main Class. The first part are the comments. The second part represents the definition of a Title for the Scene.

// Set the Title to the Stage
primaryStage.setTitle("A simple FXGraph Example");

The modified file looks like this:

Main.java

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXMLLoader;

public class Main extends Application 
{
	@Override
	public void start(Stage primaryStage) 
	{
		try 
		{
			// Load the FXML File
			BorderPane root = (BorderPane)FXMLLoader.load
					(getClass().getResource("BorderPaneExample.fxml"));
			// Create the Scene
			Scene scene = new Scene(root,400,400);
			// Add the StyleSheet to the Scene
			scene.getStylesheets().add
				(getClass().getResource("application.css")
				.toExternalForm());
			// Set the Title to the Stage
			primaryStage.setTitle("A simple FXGraph Example");
			// Add the Scene to the Stage
			primaryStage.setScene(scene);
			// Show the Stage
			primaryStage.show();
		} 
		catch(Exception e) 
		{
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) 
	{
		launch(args);
	}
}

2.7 The GUI

The following Image shows the GUI after excuting the program:

A simple FXGraph Example
A simple FXGraph Example

3. A more complex FXGraph Example

In the second example, we will create a VBox, which contains a list of children. Another difference to the previous example is the fact, that we want to define a Style for the VBox.

3.1 Creation of the FXGraph Project

At first, you have to create the Project. The steps are the same like in the last one. Only one Dialog differs, because we want to use the VBox as the Root-Type:

Creation of a FXGraph Project with a VBox as Root-Type
Creation of a FXGraph Project with a VBox as Root-Type

3.2 Changing the FXGraph File

At first we have to modify the created “VBoxExample.fxgraph”, which contains the following code:

VBoxExample.fxgraph

import javafx.scene.layout.VBox
import application.VBoxControllerExample

component VBoxExample controlledby VBoxControllerExample 
{
	VBox 
	{
		//TODO Add Nodes
	}
}

After modification the file looks like this:

VBoxExample.fxgraph

import javafx.scene.control.*
import javafx.scene.layout.*

import application.VBoxControllerExample

component VBoxExample controlledby VBoxControllerExample 
{
	VBox 
	{
		children:
		[
			Label
			{
				alignment: "CENTER_LEFT",
				cache: "true",
				cacheHint:"SCALE", 
				prefHeight:"30.0", 
				prefWidth:"200.0", 
				text:"Please insert Your Input here:", 
				textAlignment:"LEFT"			
			},
			TextField id inputText
			{
				prefWidth:"100.0"
			},
			Button
			{
				alignment:"CENTER_RIGHT",
				contentDisplay:"CENTER",
				mnemonicParsing:"false",
				onAction: controllermethod printOutput,
				text:"OK",
				textAlignment:"CENTER"
			},
			Label
			{
				alignment: "CENTER_LEFT",
				cache: "true",
				cacheHint:"SCALE", 
				prefHeight:"30.0", 
				prefWidth:"200.0", 
				text:"Your Input:", 
				textAlignment:"LEFT"			
			},
			TextArea id outputText
			{
				prefHeight:"100.0",
				prefWidth:"200.0",
				wrapText:"true"
			}
		]
	}
}

At first we have defined a list of children under the Root Node:

VBox 
{
	children:
	[
		Label
		{
			alignment: "CENTER_LEFT",
			cache: "true",
			cacheHint:"SCALE", 
			prefHeight:"30.0", 
			prefWidth:"200.0", 
			text:"Please insert Your Input here:", 
			textAlignment:"LEFT"			
		},
		TextField id inputText
		{
			prefWidth:"100.0"
		},
		Button
		{
			alignment:"CENTER_RIGHT",
			contentDisplay:"CENTER",
			mnemonicParsing:"false",
			onAction: controllermethod printOutput,
			text:"OK",
			textAlignment:"CENTER"
		},
		Label
		{
			alignment: "CENTER_LEFT",
			cache: "true",
			cacheHint:"SCALE", 
			prefHeight:"30.0", 
			prefWidth:"200.0", 
			text:"Your Input:", 
			textAlignment:"LEFT"			
		},
		TextArea id outputText
		{
			prefHeight:"100.0",
			prefWidth:"200.0",
			wrapText:"true"
		}
	]
}

A list in JSON starts with a “[” and ends with a “]”. Thus, our list contains two Labels, a Button, a TextField and a TextArea.

The attributes of an element are the same like in a FXML File, but the name and the value of the attribute are separeted by a “:”. If you want to learn more about FXML, please read my JavaFX FXML Tutorial.

The following code snippet shows an example of the definition of a Label:

Label
{
	alignment: "CENTER_LEFT",
	cache: "true",
	cacheHint:"SCALE", 
	prefHeight:"30.0", 
	prefWidth:"200.0", 
	text:"Please insert Your Input here:", 
	textAlignment:"LEFT"			
}

FXML propagates a clean separation between the UI defined in the FXML file and business logic implemented in a programming language like Java. So you can use the id for accessing objects by a controller:

TextField id inputText
{
	prefWidth:"100.0"
},
TextArea id outputText
{
	prefHeight:"100.0",
	prefWidth:"200.0",
	wrapText:"true"
}

In the above code snippet, the TextField get´s the “id” inputText and the TextArea the “id” outputText.

Referencing methods in the Controller Class like in the following example is quite easy using the controllermethod keyword:

Button
{
	alignment:"CENTER_RIGHT",
	contentDisplay:"CENTER",
	mnemonicParsing:"false",
	onAction: controllermethod printOutput,
	text:"OK",
	textAlignment:"CENTER"
}

In this example, the method printOutput from the Controller Class will be called, if the Button will be clicked. The effect of the method will be described in the Controller Class.

3.3 Changing the FXML File

The generated “VBoxExample.fxml” file looks like this:

VBoxExample.fxml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
	Do not edit this file it is generated by e(fx)clipse from ../src/application/VBoxExample.fxgraph
-->

<?import java.lang.*?>
<?import javafx.scene.layout.VBox?>

<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="application.VBoxControllerExample">

</VBox>

The following code shows the result of the translation of the FXGraph file into FXML after execution of the program:

VBoxExample.fxml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
	Do not edit this file it is generated by e(fx)clipse from ../src/application/VBoxExample.fxgraph
-->

<?import java.lang.*?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.VBox?>

<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="application.VBoxControllerExample">

	<children>
		<Label alignment="CENTER_LEFT" cache="true" cacheHint="SCALE" prefHeight="30.0" prefWidth="200.0" text="Please insert Your Input here:" textAlignment="LEFT"/> 
		<TextField fx:id="inputText" prefWidth="100.0"/> 
		<Button alignment="CENTER_RIGHT" contentDisplay="CENTER" mnemonicParsing="false" onAction="#printOutput" text="OK" textAlignment="CENTER"/> 
		<Label alignment="CENTER_LEFT" cache="true" cacheHint="SCALE" prefHeight="30.0" prefWidth="200.0" text="Your Input:" textAlignment="LEFT"/> 
		<TextArea fx:id="outputText" prefHeight="100.0" prefWidth="200.0" wrapText="true"/> 
	</children>
</VBox>

3.4 Changing the Stylesheet

The corresponding Stylesheet is also empty after creation:

application.css

/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */

In this example, we will define a border for the VBox in the Stylesheet:

application.css

/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */

.root
{
	-fx-padding: 10;
	-fx-border-style: solid inside;
	-fx-border-width: 2;
	-fx-border-insets: 5;
	-fx-border-radius: 5;
	-fx-border-color: blue;	
}

3.5 Changing the Controller Class

The created Controller Class is empty at the beginning. In this example we have to make some changes for the Button.

VBoxControllerExample.java

public class VBoxControllerExample 
{
}

The modified class contains the following Java Code:

VBoxControllerExample.java

import java.net.URL;
import java.util.ResourceBundle;

import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;

public class VBoxControllerExample 
{
	@FXML
	// The reference of inputText will be injected by the FXML loader
	private TextField inputText;

	// The reference of outputText will be injected by the FXML loader
	@FXML
	private TextArea outputText;

	// location and resources will be automatically injected by the FXML loader
	@FXML
	private URL location;

	@FXML
	private ResourceBundle resources;

	// Add a public no-args constructor
	public VBoxControllerExample()
	{
	}

	@FXML
	private void initialize()
	{
	}

	@FXML
	private void printOutput()
	{
		outputText.setText(inputText.getText());
	}	
}

The most important changes are the definition of the inputText and outputText attributes. These attributes are used by the id keyword in the FXML File.

@FXML
// The reference of inputText will be injected by the FXML loader
private TextField inputText;

// The reference of outputText will be injected by the FXML loader
@FXML
private TextArea outputText;

We also have to define the method printOutput, which will be called on a Click of our Button. The method copies only the input from the TextField into the TextArea.

@FXML
private void printOutput()
{
	outputText.setText(inputText.getText());
}	

The other methods and some usefull information is described in the JavaFX FXML Controller Example.

3.6 Changing the Main Class

The generated Main Class is very similar to the Main Class in the last example:

Main.java

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.fxml.FXMLLoader;


public class Main extends Application 
{
	@Override
	public void start(Stage primaryStage) 
	{
		try 
		{
			VBox root = (VBox)FXMLLoader.load
				(getClass().getResource("VBoxExample.fxml"));
			Scene scene = new Scene(root,400,400);
			scene.getStylesheets().add(getClass()
				.getResource("application.css")
				.toExternalForm());
			primaryStage.setScene(scene);
			primaryStage.show();
		} 
		catch(Exception e) 
		{
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) 
	{
		launch(args);
	}
}

The only one difference is the fact, that we are using a VBox instead of the BorderPane:

Main.java

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.fxml.FXMLLoader;

public class Main extends Application 
{
	@Override
	public void start(Stage primaryStage) 
	{
		try 
		{
			// Load the FXML File
			VBox root = (VBox)FXMLLoader.load
				(getClass().getResource("VBoxExample.fxml"));
			// Create the Scene
			Scene scene = new Scene(root,400,400);
			// Add the StyleSheet to the Scene
			scene.getStylesheets().add(getClass()
				.getResource("application.css")
				.toExternalForm());
			// Set the Title to the Stage
			primaryStage.setTitle("A FXGraph Example with a Controller");
			// Add the Scene to the Stage
			primaryStage.setScene(scene);
			// Show the Stage
			primaryStage.show();
		} 
		catch(Exception e) 
		{
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) 
	{
		launch(args);
	}
}

3.7 The GUI

The following image shows the GUI after starting the program and inserting a Text on the TextField:

A FXGraph Example with a Controller
A FXGraph Example with a Controller

If you press the OK Button, the Text from the TextField will be copied into the TextArea:

The GUI of the FXGraph Example after pressing the OK Button
The GUI of the FXGraph Example after pressing the OK Button

4. Download Java Source Code

This was an example of FXGraph

Download
You can download the full source code of this example here: JavaFXFXGraph.zip

Andreas Pomarolli

Andreas has graduated from Computer Science and Bioinformatics at the University of Linz. During his studies he has been involved with a large number of research projects ranging from software engineering to data engineering and at least web engineering. His scientific focus includes the areas of software engineering, data engineering, web engineering and project management. He currently works as a software engineer in the IT sector where he is mainly involved with projects based on Java, Databases and Web Technologies.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button