JavaFX effects
last modified October 18, 2023
JavaFX contains the javafx.scene.effect
package, which has a set or classes
that perform various visual effects. In this chapter, we create a DropShadow
,
a Reflection
, a Lighting
, a GaussianBlur
, a SepiaTone
,
and a PerspectiveTransform
effect. We also show how to combine multiple effects.
Effects are applied to the node's effectProperty
with the setEffect
method.
JavaFX DropShadow
DropShadow
is a high-level effect that renders a shadow behind the
content with the specified colour, radius, and offset.
package com.zetcode; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.effect.DropShadow; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; public class DropShadowEx extends Application { @Override public void start(Stage stage) { initUI(stage); } private void initUI(Stage stage) { var root = new StackPane(); var rect = new Rectangle(0, 0, 100, 100); rect.setFill(Color.GREENYELLOW); var ds = new DropShadow(15, Color.DARKGREEN); rect.setEffect(ds); root.getChildren().add(rect); var scene = new Scene(root, 250, 200, Color.WHITESMOKE); stage.setTitle("DropShadow"); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
The example creates a shadow around a rectangle.
var rect = new Rectangle(0, 0, 100, 100); rect.setFill(Color.GREENYELLOW);
A greenyellow rectangle shape is constructed.
var ds = new DropShadow(15, Color.DARKGREEN);
A DropShadow
effect is created. The constructor
accepts the radius and the colour.
rect.setEffect(ds);
The effect is applied with the setEffect
method.
JavaFX Reflection
Reflection
is an effect that renders a reflected version of the
input below the actual input content.
package com.zetcode; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.effect.Reflection; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.text.FontWeight; import javafx.scene.text.Text; import javafx.stage.Stage; public class ReflectionEx extends Application { @Override public void start(Stage stage) { initUI(stage); } private void initUI(Stage stage) { var root = new StackPane(); var text = new Text(); text.setText("ZetCode"); text.setFill(Color.STEELBLUE); text.setFont(Font.font("Serif", FontWeight.BOLD, 60)); var ref = new Reflection(); text.setEffect(ref); root.getChildren().add(text); var scene = new Scene(root, 300, 250, Color.WHITESMOKE); stage.setTitle("Reflection"); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
The example applies a Reflection
effect on a Text
node.
var text = new Text(); text.setText("ZetCode"); text.setFill(Color.STEELBLUE); text.setFont(Font.font("Serif", FontWeight.BOLD, 60));
A Text
control is created. Its paint is steelblue. The font is made bold
and enlarged.
var ref = new Reflection(); text.setEffect(ref);
A default Reflection
is created and applied on the text control.
JavaFX Lighting
Lighting
simulates a light source shining on the given content, which can
be used to give flat objects a more realistic, three-dimensional appearance.
The setAzimuth
method of the Light
source sets the
azimuth—the direction angle for the light source.
package com.zetcode; import javafx.application.Application; import javafx.beans.property.SimpleDoubleProperty; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Slider; import javafx.scene.effect.Light; import javafx.scene.effect.Lighting; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.text.FontWeight; import javafx.scene.text.Text; import javafx.stage.Stage; public class LightingEx extends Application { @Override public void start(Stage stage) { initUI(stage); } private void initUI(Stage stage) { var root = new VBox(30); root.setPadding(new Insets(10)); var azimuth = new SimpleDoubleProperty(0); Light.Distant light = new Light.Distant(); light.setAzimuth(0); var lighting = new Lighting(light); lighting.setSurfaceScale(5.0); var text = new Text(); text.setText("ZetCode"); text.setFill(Color.LIGHTSKYBLUE); text.setFont(Font.font(null, FontWeight.BOLD, 60)); var slider = new Slider(1, 360, 0); azimuth.bind(slider.valueProperty()); slider.valueProperty().addListener(event -> { light.setAzimuth(azimuth.get()); lighting.setLight(light); text.setEffect(lighting); }); text.setEffect(lighting); root.getChildren().addAll(slider, text); var scene = new Scene(root, 300, 250, Color.WHITESMOKE); stage.setTitle("Lighting"); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
The example applies a Lighting
effect on a Text
control.
The azimuth of the light is controlled by a Slider
.
Light.Distant light = new Light.Distant(); light.setAzimuth(0);
A Light
source is created.
var lighting = new Lighting(light);
This line creates a new instance of a Lighting
with
the specified light.
var text = new Text(); text.setText("ZetCode"); text.setFill(Color.LIGHTSKYBLUE); text.setFont(Font.font(null, FontWeight.BOLD, 60));
This is the Text
control on which the Lighting
effect is set.
var slider = new Slider(1, 360, 0); azimuth.bind(slider.valueProperty()); slider.valueProperty().addListener(event -> { light.setAzimuth(azimuth.get()); lighting.setLight(light); text.setEffect(lighting); });
The Slider
control manages the azimuth of the light source.
JavaFX GaussianBlur
GaussianBlur
is a blur effect using a Gaussian convolution
kernel with a configurable radius.
package com.zetcode; import javafx.application.Application; import javafx.beans.property.SimpleDoubleProperty; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Slider; import javafx.scene.effect.GaussianBlur; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.stage.Stage; public class GaussianBlurEx extends Application { @Override public void start(Stage stage) { initUI(stage); } private void initUI(Stage stage) { var root = new VBox(30); root.setPadding(new Insets(10)); var radius = new SimpleDoubleProperty(0); var blurredText = new Text("Inception"); blurredText.setFont(Font.font(38)); var slider = new Slider(1, 20, 1); radius.bind(slider.valueProperty()); slider.valueProperty().addListener(event -> { blurredText.setEffect(new GaussianBlur(radius.get())); }); root.getChildren().addAll(slider, blurredText); var scene = new Scene(root, 300, 250, Color.WHITESMOKE); stage.setTitle("Blur effect"); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
The example applies a GaussianBlur
effect on a Text
control. The radius of the blur is controlled by a Slider
.
var blurredText = new Text("Inception"); blurredText.setFont(Font.font(38));
The blur effect will be applied on this text control.
var slider = new Slider(1, 20, 1); radius.bind(slider.valueProperty()); slider.valueProperty().addListener(event -> { blurredText.setEffect(new GaussianBlur(radius.get())); });
The Slider
control manages the radius
property
of the GaussianBlur
effect.
JavaFX SepiaTone
SepiaTone
is a filter that produces a sepia tone effect,
similar to antique photographs.
package com.zetcode; import javafx.application.Application; import javafx.beans.binding.Bindings; import javafx.scene.CacheHint; import javafx.scene.Scene; import javafx.scene.effect.Effect; import javafx.scene.effect.SepiaTone; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.stage.Stage; public class SepiaToneEx extends Application { @Override public void start(Stage stage) { initUI(stage); } private void initUI(Stage stage) { var root = new StackPane(); var image = new Image("file:src/main/resources/mushroom.png"); var iw = new ImageView(image); var sepia = new SepiaTone(); iw.effectProperty().bind( Bindings.when(iw.hoverProperty()) .then((Effect) sepia) .otherwise((Effect) null) ); iw.setCache(true); iw.setCacheHint(CacheHint.SPEED); root.getChildren().add(iw); var scene = new Scene(root); stage.setTitle("SepiaTone"); scene.setFill(Color.WHITESMOKE); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
The example applies a SepiaTone
effect
on an Image
when a mouse pointer is over the image.
var image = new Image("file:src/main/resources/mushroom.png"); var iw = new ImageView(image);
We load an Image
from the disk and create an ImageView
control.
var sepia = new SepiaTone(); iw.effectProperty().bind( Bindings.when(iw.hoverProperty()) .then((Effect) sepia) .otherwise((Effect) null) );
The SepiaTone
effect is set when the mouse pointer is located
over the bounds of the ImageView
control.
iw.setCache(true); iw.setCacheHint(CacheHint.SPEED);
For performance reasons, the node rendering is cached.
JavaFX PerspectiveTransform
PerspectiveTransform
provides a non-affine transformation of the input content.
It is usually used to create a three-dimensional effect on a two-dimensional content.
package com.zetcode; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.effect.PerspectiveTransform; import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; public class PerspectiveEx extends Application { private final int SIZE = 50; @Override public void start(Stage stage) { initUI(stage); } private void initUI(Stage stage) { var root = new StackPane(); var board = new Pane(); for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { var r = new Rectangle(col * SIZE, row*SIZE, SIZE, SIZE); if ((col+row) % 2 == 0) { r.setFill(Color.WHITE); } else { r.setFill(Color.BLACK); } board.getChildren().add(r); } } var e = new PerspectiveTransform(); e.setUlx(30); // Upper-left point e.setUly(170); e.setUrx(370); // Upper-right point e.setUry(170); e.setLlx(0); // Lower-left point e.setLly(300); e.setLrx(400); // Lower-right point e.setLry(300); board.setEffect(e); root.getChildren().add(board); var scene = new Scene(root, Color.WHITESMOKE); stage.setTitle("ChessBoard"); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
The example forms a chessboard with the PerspectiveTransform
effect.
for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { var r = new Rectangle(col * SIZE, row*SIZE, SIZE, SIZE); if ((col+row) % 2 == 0) { r.setFill(Color.WHITE); } else { r.setFill(Color.BLACK); } board.getChildren().add(r); } }
This code produces 64 rectangles. The rectangles have black and white colours.
var e = new PerspectiveTransform(); e.setUlx(30); // Upper-left point e.setUly(170); e.setUrx(370); // Upper-right point e.setUry(170); e.setLlx(0); // Lower-left point e.setLly(300); e.setLrx(400); // Lower-right point e.setLry(300); board.setEffect(e);
A PerspectiveTransform
is instantiated and applied on the node.
We provide x and y coordinates of four corner points. These points
form a rectangle into which the effect is rendered.
JavaFX Combining effects
It is possible to combine effects. The setEffect
method replaces
an effect if there is one already set. To combine multiple effects, we use
the Effect's
setInput
method.
package com.zetcode; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.effect.Light; import javafx.scene.effect.Lighting; import javafx.scene.effect.Reflection; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.text.FontWeight; import javafx.scene.text.Text; import javafx.stage.Stage; public class CombiningEffectsEx extends Application { @Override public void start(Stage stage) { initUI(stage); } private void initUI(Stage stage) { var root = new StackPane(); Light.Distant light = new Light.Distant(); light.setAzimuth(50); var lighting = new Lighting(); lighting.setLight(light); lighting.setSurfaceScale(5); var text = new Text(); text.setText("ZetCode"); text.setFill(Color.CADETBLUE); text.setFont(Font.font(null, FontWeight.BOLD, 60)); var ref = new Reflection(); ref.setInput(lighting); text.setEffect(ref); root.getChildren().add(text); var scene = new Scene(root, 300, 250, Color.WHITESMOKE); stage.setTitle("Combining effects"); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
The example program combines a Reflection
effect
with a Lighting
effect on a Text
node.
Light.Distant light = new Light.Distant(); light.setAzimuth(50); var lighting = new Lighting(); lighting.setLight(light); lighting.setSurfaceScale(5.0);
These lines create a Lighting
effect.
var text = new Text(); text.setText("ZetCode"); text.setFill(Color.CADETBLUE); text.setFont(Font.font(null, FontWeight.BOLD, 60));
A Text
control is created. The font is enlarged and bold face.
The colour of the text is cadetblue.
var ref = new Reflection(); ref.setInput(lighting);
A Reflection
effect is constructed. It is combined with the
lighting effect using the setInput
method.
text.setEffect(ref);
The final combination of effects is applied on the node with the setEffect
method.
In this chapter, we have created several visual effects.