JavaFX

JavaFX Transformation Example

This is a JavaFX Transformation Example. A transformation is a mapping of points in a coordinate space to themselves preserving distances and directions between them. Several types of transformations can be applied to points in a coordinate space. JavaFX supports the following types of transformation:

  • Translation
  • Rotation
  • Shear
  • Scale

An instance of the abstract Transform class represents a transformation in JavaFX. The Transform class contains common methods and properties used by all types of transformations on nodes. It contains factory methods to create specific types of transformations.

 
The following table shows an overview of the whole article:

The following examples use Java SE 8 and JavaFX 2.2.

1. The Translation Transformation

1.1 The Code

FxTransformationExample1.java

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class FxTransformationExample1 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	@Override
	public void start(Stage stage) 
	{
		// Create the Rectangles
		Rectangle rectangle1 = new Rectangle(100, 50, Color.LIGHTGRAY);
		rectangle1.setStroke(Color.BLACK);
		Rectangle rectangle2 = new Rectangle(100, 100, Color.YELLOW);
		rectangle2.setStroke(Color.BLACK);
		Rectangle rectangle3 = new Rectangle(180, 100, Color.STEELBLUE);
		rectangle3.setStroke(Color.BLACK);
		
		// Apply a Translation on Rectangle1 using the transforms sequence
		Translate translate1 = new Translate(50, 40);
		rectangle1.getTransforms().addAll(translate1);
		
		// Apply a Translation on Rectangle2 using the transforms sequence
		Translate translate2 = new Translate(100, 80);
		rectangle2.getTransforms().addAll(translate2);

		// Apply a Translation on Rectangle3 using the translateX and translateY proeprties
		rectangle3.setTranslateX(180);
		rectangle3.setTranslateY(70);
		
		// Create the Pane
		Pane root = new Pane(rectangle1, rectangle2, rectangle3);
		// Set the size of the Pane
		root.setPrefSize(400, 300);
		// Set the Style-properties of the Pane
		root.setStyle("-fx-padding: 10;" +
				"-fx-border-style: solid inside;" +
				"-fx-border-width: 2;" +
				"-fx-border-insets: 5;" +
				"-fx-border-radius: 5;" +
				"-fx-border-color: blue;");
		
		// Create the Scene
		Scene scene = new Scene(root);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the title of the Stage
		stage.setTitle("A Translation Transformation Example");
		// Display the Stage
		stage.show();		
	}
}

A translation moves every point of a Node by a fixed distance in a specified direction relative to its parent coordinate system. It is achieved by shifting the origin of the local coordinate system of the Node to a new location.

Computing the new locations of points is easy. You only have to add a triplet of numbers to the coordinates of each point in a 3D space. In a 2D space, add a pair of numbers to the coordinates of each point.

Suppose you want to apply translation to a 3D coordinate space by (tx, ty, tz). If a point had coordinates (x, y, z) before the translation, after the translation its coordinates would be (x + tx, y + ty, z + tz).

An instance of the Translate class represents a translation. It contains three properties.

  • x
  • y
  • z

The properties specify the x, y, and z coordinates of the new origin of the local coordinate system of the node after translation. The default values for the properties are 0.0.

The Translate class provides three constructors.

  • Translate()
  • Translate(double x, double y)
  • Translate(double x, double y, double z)

The no-args constructor creates a Translate object with the default values for the x, y, and z properties, which, in essence, represents no Translation. The other two constructors let you specify the Translation distance along the three axes.

The following code snippet shows the usage of the constructor:

// Apply a Translation on Rectangle1 using the transforms sequence
Translate translate1 = new Translate(50, 40);

A transformation to a Group is applied to all the nodes in the Group.

1.2 The GUI

The above program creates three rectangles. By default, they are placed at (0, 0). It applies a translation to all rectangles. The following Figure shows the rectangles after the translation.

A JavaFX Translation Transformation Example
A JavaFX Translation Transformation Example

2. The Rotation Transformation

2.1 The Code

FxTransformationExample2.java

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class FxTransformationExample2 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	@Override
	public void start(Stage stage) 
	{
		// Create the Rectangles
		Rectangle rectangle1 = new Rectangle(150, 100, Color.LIGHTGRAY);
		rectangle1.setStroke(Color.BLACK);
		Rectangle rectangle2 = new Rectangle(150, 100, Color.LIGHTGRAY);
		rectangle2.setStroke(Color.BLACK);

		// Create a Translation
		Translate translate = new Translate(150, 30);

		// Apply a Translation on Rectangle1 using the transforms sequence
		rectangle1.getTransforms().addAll(translate);
		
		// Apply a Translation on Rectangle2 using the transforms sequence
		rectangle2.getTransforms().addAll(translate);
		rectangle2.setOpacity(0.5);
		
		// Apply a Rotation on Rectangle2
		Rotate rotate = new Rotate(60, 0, 0);
		rectangle2.getTransforms().addAll(rotate);

		// Create the Pane
		Pane root = new Pane(rectangle1, rectangle2);
		// Set the size of the Pane
		root.setPrefSize(400, 300);
		// Set the Style-properties of the Pane
		root.setStyle("-fx-padding: 10;" +
				"-fx-border-style: solid inside;" +
				"-fx-border-width: 2;" +
				"-fx-border-insets: 5;" +
				"-fx-border-radius: 5;" +
				"-fx-border-color: blue;");
		
		// Create the Scene
		Scene scene = new Scene(root);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the Title of the Stage
		stage.setTitle("A Rotation Transformation Example");
		// Display the Stage
		stage.show();
	}
}

In a rotation transformation, the axes are rotated around a pivot point in the coordinate space and the coordinates of points are mapped to the new axes.

An instance of the Rotate class represents a rotation transformation. It contains five properties to describe the rotation:

  • angle
  • axis
  • pivotX
  • pivotY
  • pivotZ

The angle property specifies the angle of rotation in degrees. The default is 0.0 degrees. A positive value for the angle is measured clockwise.

The axis property specifies the axis of rotation at the pivot point. Its value can be one of the constants, X_AXIS, Y_AXIS, and Z_AXIS, defined in the Rotate class. The default axis of rotation is Rotate.Z_AXIS.

The pivotX, pivotY, and pivotZ properties are the x, y, and z coordinates of the pivot point. The default values for the properties are 0.0.

The Rotate class contains several constructors:

  • Rotate()
  • Rotate(double angle)
  • Rotate(double angle, double pivotX, double pivotY)
  • Rotate(double angle, double pivotX, double pivotY, double pivotZ)
  • Rotate(double angle, double pivotX, double pivotY, double pivotZ, Point3D axis)
  • Rotate(double angle, Point3D axis)

The no-args constructor creates an identity rotation, which does not have any effect on the transformed Node. The other constructors let you specify the details.

The following code snippet shows an example of the constructor:

// Apply a Rotation on Rectangle2
Rotate rotate = new Rotate(60, 0, 0);

2.2 The GUI

The above program creates two rectangles and places them at the same location. The opacity of the second Rectangle is set to 0.5, so we can see through it. The coordinate system of the second Rectangle is rotated by 60 degrees in the clockwise direction using the origin as the pivot point.

The following Image shows the rotated rectangle.

A JavaFX Rotation Transformation Example
A JavaFX Rotation Transformation Example

3. The Scale Transformation

3.1 The Code

FxTransformationExample3.java

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class FxTransformationExample3 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	@Override
	public void start(Stage stage) 
	{
		// Create the Rectangles
		Rectangle rectangle1 = new Rectangle(200, 150, Color.LIGHTGRAY);
		rectangle1.setStroke(Color.BLACK);
		rectangle1.setOpacity(0.5);
		Rectangle rectangle2 = new Rectangle(200, 150, Color.GREEN);
		rectangle2.setStroke(Color.BLACK);

		// Create the Translations
		Translate translate1 = new Translate(200, 100);
		Translate translate2 = new Translate(100, 50);

		// Apply a Translation on Rectangle1
		rectangle1.getTransforms().addAll(translate2);
		
		// Apply a Translation on Rectangle2
		rectangle2.getTransforms().addAll(translate1);
		
		// Apply a Scale on Rectangle
		rectangle2.setScaleX(0.5);
		rectangle2.setScaleY(0.5);

		// Create the Pane
		Pane root = new Pane(rectangle1, rectangle2);
		// Set the size of the Pane
		root.setPrefSize(400, 300);
		// Set the Style-properties of the Pane
		root.setStyle("-fx-padding: 10;" +
				"-fx-border-style: solid inside;" +
				"-fx-border-width: 2;" +
				"-fx-border-insets: 5;" +
				"-fx-border-radius: 5;" +
				"-fx-border-color: blue;");
		
		// Create the Scene
		Scene scene = new Scene(root);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the Title of the Stage
		stage.setTitle("A Scale Transformation Example");
		// Display the Stage
		stage.show();
	}
}

A scale transformation scales the unit of measurement along axes of a coordinate system by a scale factor. This causes the dimensions of a Node to change (stretch or shrink) by the specified scale factors along axes. The dimension along an axis is multiplied by the scale factor along that axis. The transformation is applied at a pivot point whose coordinates remain the same after the transformation.

An instance of the Scale class represents a Scale transformation. It contains the following six properties to describe the transformation:

  • x
  • y
  • z
  • pivotX
  • pivotY
  • pivotZ

The x, y, and z properties specify the scale factors long the x-axis, y-axis, and z-axis. They are 1.0 by default.

The pivotX, pivotY, and pivotZ properties are the x, y, and z coordinates of the pivot point. The default values for the properties are 0.0.

The Scale class contains several constructors.

  • Scale()
  • Scale(double x, double y)
  • Scale(double x, double y, double z)
  • Scale(double x, double y, double pivotX, double pivotY)
  • Scale(double x, double y, double z, double pivotX, double pivotY, double pivotZ)

The no-args constructor creates an identity Scale transformation, which does not have any effect on the transformed Node. The other constructors let you specify the scale factors and the pivot point.

The following snippet of code applies a Scale on a Rectangle by usage of the Setters.

// Apply a Scale on Rectangle
rectangle2.setScaleX(0.5);
rectangle2.setScaleY(0.5);

You can use an object of the Scale class or the scaleX, scaleY, and scaleZ properties of the Node class to apply a Scale transformation. By default, the pivot point used by the Scale class is at (0, 0, 0). The properties of the Node class use the center of the node as the pivot point.

3.2 The GUI

The above Java Class creates two rectangles. Both are placed at the same location. One of them is scaled and the other not. The opacity of the not scaled Rectangle is set to 0.5, so we can see through it.

The following GUI shows the rectangles. The scaled Rectangle is smaller. The coordinate system of the second Rectangle is scaled by 0.5 along the x-axis and 0.5 along the y-axis. The scaleX and scaleY properties are used to apply the transformation, which uses the center of the rectangles as the pivot point making the rectangles shrunk, but keeping it at the same location.

A JavaFX Scale Transformation Example
A JavaFX Scale Transformation Example

4. The Shear Transformation

4.1 The Code

FxTransformationExample4.java

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Shear;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class FxTransformationExample4 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	@Override
	public void start(Stage stage) 
	{
		// Create the Rectangles		
		Rectangle rectangle1 = new Rectangle(200, 100, Color.LIGHTGRAY);
		rectangle1.setStroke(Color.BLACK);
		Rectangle rectangle2 = new Rectangle(200, 100, Color.LIGHTGREEN);
		rectangle2.setStroke(Color.BLACK);
		
		// Create a Translation
		Translate translate = new Translate(100, 30);

		// Apply a Translation on Rectangle1 using the transforms sequence
		rectangle1.getTransforms().addAll(translate);
		
		// Apply a Translation on Rectangle2 using the transforms sequence
		rectangle2.getTransforms().addAll(translate);
		rectangle2.setOpacity(0.5);

		// Apply a Shear on Rectangle2
		Shear shear = new Shear(0.5, 0.5);
		rectangle2.getTransforms().addAll(shear);

		// Create the Pane
		Pane root = new Pane(rectangle1, rectangle2);
		// Set the size of the Pane
		root.setPrefSize(400, 300);
		// Set the Style-properties of the Pane
		root.setStyle("-fx-padding: 10;" +
				"-fx-border-style: solid inside;" +
				"-fx-border-width: 2;" +
				"-fx-border-insets: 5;" +
				"-fx-border-radius: 5;" +
				"-fx-border-color: blue;");
		
		// Create the Scene
		Scene scene = new Scene(root);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the Title of the Stage
		stage.setTitle("A Shear Transformation Example");
		// Display the Stage
		stage.show();
	}
}

A shear transformation rotates axes of the local coordinate system of the Node around a pivot point, so the axes are no longer perpendicular. A rectangular Node becomes a parallelogram after the transformation.

An instance of the Shear class represents a shear transformation. It contains four properties to describe the transformation.

  • x
  • y
  • pivotX
  • pivotY

The x property specifies a multiplier by which the coordinates of points are shifted along the positive x-axis by a factor of the y coordinate of the point. The default is 0.0.

The y property specifies a multiplier by which the coordinates of points are shifted along the positive y-axis by a factor of the x coordinate of the point. The default is 0.0.

The pivotX, and pivotY properties are the x and y coordinates of the pivot point about which the shear occurs. The default values for them are 0.0. The pivot point is not shifted by the Shear.

By default, the pivot point is the origin of the untransformed coordinate system.
Suppose you have a point (x1, y1) inside a Node, and by the Shear transformation, the point is shifted to (x2, y2). You can use the following formula to compute (x2, y2):

x2 = pivotX + (x1 - pivotX) + x * (y1 - pivotY)
y2 = pivotY + (y1 - pivotY) + y * (x1 - pivotX)

All coordinates (x1, y1, x2, and y2) in the previous formula are in the untransformed local coordinate system of the Node. Notice that if (x1, y1) is the pivot point, the foregoing formula computes the shifted point (x2, y2), which is the same as (x1, y1). That is, the pivot point is not shifted.

The Shear class contains several constructors.

  • Shear()
  • Shear(double x, double y)
  • Shear(double x, double y, double pivotX, double pivotY)

The no-args constructor creates an identity Shear transformation, which does not have any effect on the transformed Node. The other constructors let you specify the shear multipliers and the pivot point.

The following code snippet applies a Shear on the second Rectangle.

// Apply a Shear on Rectangle2
Shear shear = new Shear(0.5, 0.5);

4.2 The GUI

The above program applies a Shear to a Rectangle as shown in the following GUI. The original Rectangle is also shown. A multiplier of 0.5 is used along both axes. Note that the pivot point is (100, 30).

A JavaFX Shear Transformation Example
A JavaFX Shear Transformation Example

5. Applying Multiple Transformations

5.1 The Code

FxTransformationExample5.java

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class FxTransformationExample5 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	@Override
	public void start(Stage stage) 
	{
		// Create the Rectangles
		Rectangle rectangle1 = new Rectangle(150, 100, Color.LIGHTGRAY);
		rectangle1.setStroke(Color.BLACK);
		Rectangle rectangle2 = new Rectangle(150, 100, Color.LIGHTBLUE);
		rectangle2.setStroke(Color.BLACK);
		Rectangle rectangle3 = new Rectangle(150, 100, Color.LIGHTCYAN);
		rectangle3.setStroke(Color.BLACK);
	
		// Create a Translation
		Translate translate = new Translate(100, 40);

		// Apply a Translation on Rectangle1 using the transforms sequence
		rectangle1.getTransforms().addAll(translate);
		
		// Apply a Translation on Rectangle2 using the transforms sequence
		rectangle2.getTransforms().addAll(translate);
		rectangle2.setOpacity(0.5);

		// Apply a Translation on Rectangle3 using the transforms sequence
		rectangle3.getTransforms().addAll(translate);
		rectangle3.setOpacity(0.5);
		
		//Apply Transformations to Rectangle2
		rectangle2.setTranslateX(100);
		rectangle2.setTranslateY(0);
		rectangle2.setRotate(30);
		rectangle2.setScaleX(1.2);
		rectangle2.setScaleY(1.2);
		
		// Apply Transformation to Rectangle3
		rectangle3.getTransforms().addAll(new Scale(1.2, 1.2, 50, 25),
				new Rotate(30, 50, 25),new Translate(100, 0));

		// Create the Pane
		Pane root = new Pane();
		// Set the size of the Pane
		root.setPrefSize(400, 300);
		// Add the Children to the Pane
		root.getChildren().addAll(rectangle1, rectangle2, rectangle3);
		// Set the Style-properties of the Pane
		root.setStyle("-fx-padding: 10;" +
				"-fx-border-style: solid inside;" +
				"-fx-border-width: 2;" +
				"-fx-border-insets: 5;" +
				"-fx-border-radius: 5;" +
				"-fx-border-color: blue;");
		
		// Create the Scene
		Scene scene = new Scene(root);
		// Add the Scene to the Stage
		stage.setScene(scene);
		// Set the Title of the Stage
		stage.setTitle("A Multiple Transformations Example");
		// Display the Stage
		stage.show();		
	}
}

You can apply multiple transformations to a Node. As mentioned previously, the transformations in the transforms sequence are applied before the transformation set on the properties of the Node.

When properties of the Node class are used, Translation, Rotation, and Scale are applied in sequence. When the transforms sequence is used, transformations are applied in the order they are stored in the sequence.

The following code snippet creates three rectangles and positions them at the same location. It applies multiple transformations to the second and third rectangles in different order.

// Create a Translation
Translate translate = new Translate(100, 40);

// Apply a Translation on Rectangle1 using the transforms sequence
rectangle1.getTransforms().addAll(translate);

// Apply a Translation on Rectangle2 using the transforms sequence
rectangle2.getTransforms().addAll(translate);
rectangle2.setOpacity(0.5);

// Apply a Translation on Rectangle3 using the transforms sequence
rectangle3.getTransforms().addAll(translate);
rectangle3.setOpacity(0.5);

//Apply Transformations to Rectangle2
rectangle2.setTranslateX(100);
rectangle2.setTranslateY(0);
rectangle2.setRotate(30);
rectangle2.setScaleX(1.2);
rectangle2.setScaleY(1.2);

The first Rectangle is shown at its original position, as we did not apply any transformation to it. Notice that two rectangles ended up at different locations. If you change the order of the transformation for the third Rectangle as shown next, both rectangles will overlap.

// Apply Transformation to Rectangle3
rectangle3.getTransforms().addAll(new Scale(1.2, 1.2, 50, 25),
		new Rotate(30, 50, 25),new Translate(100, 0));

5.2 The GUI

The following GUI shows the result of the above program.

A JavaFX Multiple Transformation Example
A JavaFX Multiple Transformation Example

6. Download Java Source Code

This was an example of javafx.scene.transform

Download
You can download the full source code of this example here: JavaFxTransformationExample.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