JavaFX effects

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.

DropShadow

DropShadow is a high-level effect that renders a shadow behind the content with the specified colour, radius, and offset.

DropShadowEx.java
package com.zetcod;

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;

/**
 * ZetCode JavaFX tutorial
 *
 * This program applies a DropShadow effect
 * on a Rectangle.
 *
 * Author: Jan Bodnar
 * Website: zetcode.com
 * Last modified: June 2015
 */

public class DropShadowEx extends Application {

    @Override
    public void start(Stage stage) {

        initUI(stage);
    }

    private void initUI(Stage stage) {

        StackPane root = new StackPane();
        
        Rectangle rect = new Rectangle(0, 0, 100, 100);
        rect.setFill(Color.GREENYELLOW);
        
        DropShadow ds = new DropShadow(15, Color.DARKGREEN);
        
        rect.setEffect(ds);
        
        root.getChildren().add(rect);

        Scene 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.

Rectangle rect = new Rectangle(0, 0, 100, 100);
rect.setFill(Color.GREENYELLOW);

A greenyellow rectangle shape is constructed.

DropShadow 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.

DropShadow
Figure: DropShadow

Reflection

Reflection is an effect that renders a reflected version of the input below the actual input content.

ReflectionEx.java
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;

/**
 * ZetCode JavaFX tutorial
 *
 * This program applies a Reflection effect
 * on a Text node.
 *
 * Author: Jan Bodnar
 * Website: zetcode.com
 * Last modified: June 2015
 */

public class ReflectionEx extends Application {

    @Override
    public void start(Stage stage) {

        initUI(stage);
    }

    private void initUI(Stage stage) {

        StackPane root = new StackPane();
        
        Text text = new Text();
        text.setText("ZetCode");
        text.setFill(Color.STEELBLUE);
        text.setFont(Font.font("Serif", FontWeight.BOLD, 60));

        Reflection ref = new Reflection();
        text.setEffect(ref);
        
        root.getChildren().add(text);        

        Scene 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.

Text 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.

Reflection ref = new Reflection();
text.setEffect(ref);

A default Reflection is created and applied on the text control.

Reflection
Figure: Reflection

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.

LightingEx.java
package com.zetcode;

import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
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;

/**
 * ZetCode JavaFX tutorial
 *
 * This program applies a Lighting effect on 
 * a Text control. The azimuth of the light is 
 * controlled by a Slider.
 *
 * Author: Jan Bodnar
 * Website: zetcode.com
 * Last modified: June 2015
 */

public class LightingEx extends Application {

    @Override
    public void start(Stage stage) {

        initUI(stage);
    }

    private void initUI(Stage stage) {
        
        VBox root = new VBox(30);
        root.setPadding(new Insets(10));
        
        DoubleProperty azimuth = new SimpleDoubleProperty(0);        

        Light.Distant light = new Light.Distant();
        light.setAzimuth(0);

        Lighting lighting = new Lighting(light);
        lighting.setSurfaceScale(5.0);

        Text text = new Text();
        text.setText("ZetCode");
        text.setFill(Color.LIGHTSKYBLUE);
        text.setFont(Font.font(null, FontWeight.BOLD, 60));
        
        Slider 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);

        Scene 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.

Lighting lighting = new Lighting(light);

This line creates a new instance of a Lighting with the specified light.

Text 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.

Slider 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.

Lighting
Figure: Lighting

GaussianBlur

GaussianBlur is a blur effect using a Gaussian convolution kernel with a configurable radius.

GaussianBlurEx.java
package com.zetcode;

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.DoubleProperty;
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;

/**
 * ZetCode JavaFX tutorial
 *
 * This program applies a GaussianBlur effect on 
 * a Text control. The radius of the blur is 
 * controlled by a Slider.
 *
 * Author: Jan Bodnar
 * Website: zetcode.com
 * Last modified: June 2015
 */

public class GaussianBlurEx extends Application {

    @Override
    public void start(Stage stage) {

        initUI(stage);
    }

    private void initUI(Stage stage) {

        VBox root = new VBox(30);
        root.setPadding(new Insets(10));
        
        DoubleProperty radius = new SimpleDoubleProperty(0);
        
        Text blurredText = new Text("Inception");
        blurredText.setFont(Font.font(38));        
        
        Slider 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);
        
        Scene 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.

Text blurredText = new Text("Inception");
blurredText.setFont(Font.font(38)); 

The blur effect will be applied on this text control.

Slider 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.

GaussianBlur
Figure: GaussianBlur

SepiaTone

SepiaTone is a filter that produces a sepia tone effect, similar to antique photographs.

SepiaToneEx.java
package com.zetcode;

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.CacheHint;
import javafx.scene.Scene;
import javafx.scene.effect.ColorAdjust;
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;

/**
 * ZetCode JavaFX tutorial
 *
 * This program applies a SepiaTone effect
 * on an Image when a mouse pointer is over
 * the image.
 *
 * Author: Jan Bodnar
 * Website: zetcode.com
 * Last modified: June 2015
 */

public class SepiaToneEx extends Application {

    @Override
    public void start(Stage stage) {

        initUI(stage);
    }

    private void initUI(Stage stage) {

        StackPane root = new StackPane();
        
        Image image = new Image("file:mushroom.png");

        ImageView iw = new ImageView(image);

        SepiaTone 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);

        Scene 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.

Image image = new Image("file:mushroom.png");
ImageView iw = new ImageView(image);

We load an Image from the disk and create an ImageView control.

SepiaTone 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.

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.

PerspectiveEx.java
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;

/**
 * ZetCode JavaFX tutorial
 *
 * This program creates a chessboard 
 * with a PerspectiveTransform effect.
 *
 * Author: Jan Bodnar
 * Website: zetcode.com
 * Last modified: June 2015
 */

public class PerspectiveEx extends Application {

    private final int SIZE = 50;

    @Override
    public void start(Stage stage) {

        initUI(stage);
    }

    private void initUI(Stage stage) {

        StackPane root = new StackPane();
        
        Pane board = new Pane();
        
        for (int row = 0; row < 8; row++) {
            for (int col = 0; col < 8; col++) {
                
                Rectangle 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);
            }
        }

        PerspectiveTransform 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);

        Scene 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++) {
        
        Rectangle 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.

PerspectiveTransform 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.

Chessboard
Figure: Chessboard

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.

CombiningEffectsEx.java
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;

/**
 * ZetCode JavaFX tutorial
 *
 * This program combines a Reflection effect 
 * with a Lighting effect on a Text node.
 *
 * Author: Jan Bodnar
 * Website: zetcode.com
 * Last modified: June 2015
 */

public class CombiningEffectsEx extends Application {

    @Override
    public void start(Stage stage) {

        initUI(stage);
    }

    private void initUI(Stage stage) {

        StackPane root = new StackPane();

        Light.Distant light = new Light.Distant();
        light.setAzimuth(50);

        Lighting lighting = new Lighting();
        lighting.setLight(light);
        lighting.setSurfaceScale(5);

        Text text = new Text();
        text.setText("ZetCode");
        text.setFill(Color.CADETBLUE);
        text.setFont(Font.font(null, FontWeight.BOLD, 60));

        Reflection ref = new Reflection();
        ref.setInput(lighting);
        text.setEffect(ref);
        
        root.getChildren().add(text);

        Scene 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);

Lighting lighting = new Lighting();
lighting.setLight(light);
lighting.setSurfaceScale(5.0);

These lines create a Lighting effect.

Text 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.

Reflection 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.

Combining effects
Figure: Combining effects

In this chapter, we have created several visual effects.