JavaFX: How to Add Shadows

By Doug Lowe

You may notice that the shadow in this JavaFX rectangle shown here doesn’t look very realistic. That’s because it’s directly behind the rectangle, as if the light source causing the shadow were dead ahead. Usually, we expect shadows to be at a slight angle from the object casting the shadow, most often below the object and offset to one side.

image0.jpg

Fortunately, the DropShadow class has several properties that let you control the size and positioning of the shadow. Those methods are listed in this table, which lists the details not only of the DropShadow class but also of its sister class, InnerShadow. The InnerShadow class creates a shadow inside of a shape instead of outside the shape. For now, focus on DropShadow.

The DropShadow and InnerShadow Classes
Constructor Explanation
DropShadow() Creates a new DropShadow effect with
default settings.
InnerShadow() Creates a new InnerShadow effect with
default settings.
Common Methods Explanation
void setColor(Color value) Sets the color to use for the shadow. The default is BLACK.
void setWidth(double value) Sets the width of the shadow. The default is 21.
void setHeight(double value) Sets the height of the shadow. The default is 21.
void setOffsetX(double value) The horizontal offset for the shadow. The default is 0.
void setOffsetY(double value) The vertical offset for the shadow. The default is 0.
void setRadius(double value) The radius of the shadow’s blur effect. The default is
10.
DropShadow Only Explanation
void setSpread (double value) The proportion (from 0.0 to 1.0) of the shadow that should be a
solid color rather than blurred. The default is 0.
InnerShadow only Explanation
void setChoke (double value) The proportion (from 0.0 to 1.0) of the shadow that should be a
solid color rather than blurred. The default is 0.

The methods of the DropShadow class allow you to specify the exact geometry of the shadow you want applied. The setWidth and setHeight methods let you specify the size of the shadow, and the setOffsetX and setOffsetY methods let you change the location of the shadow relative to the center of the shape. Typically, you’ll add a positive x- and y-offset so that the shadow appears below and to the right of the shape, like this:

DropShadow shadow1 = new DropShadow();
shadow1.setOffsetX(10);
shadow1.setOffsetY(10);

In this example, the shadow is placed 10 pixels to the right and 10 pixels below the shape.

The setRadius method lets you specify the size of the blur effect applied to the edges of the shadow. The larger this number, the fuzzier the shadow will appear. You can also control the spread, which indicates what portion of the shadow’s blur should be solid color before the blur effect kicks in.

This figure shows a JavaFX application that demonstrates nine variations of the basic drop shadow.

image1.jpg

To create these shadowed rectangles, a utility method named createShadowedBox was created. Here’s the code for this method:

Rectangle createShadowedBox(double size,
    double shadowWidth, double shadowHeight,
    double offsetX, double offsetY,
    double radius)
{
    Rectangle r = new Rectangle(size, size);
    r.setFill(Color.LIGHTGRAY);
    r.setStroke(Color.BLACK);
    r.setStrokeWidth(2);
    DropShadow e = new DropShadow();
    e.setWidth(shadowWidth);
    e.setHeight(shadowHeight);
    e.setOffsetX(offsetX);
    e.setOffsetY(offsetY);
    e.setRadius(radius);
    r.setEffect(e);
    return r;
}

As you can see, this method accepts six parameters: the size of the rectangle to create (the rectangle is actually a square, so the size is used for both the width and the height), the width and height of the shadow, the x- and y-offsets for the shadow, and the shadow’s blur radius.

The method starts by creating a rectangle. Then, it creates a drop shadow, applies the width, height, x-offset, y-offset, and radius, and then applies the effect to the rectangle and returns the rectangle.

To create the actual shadowed rectangles, the createShadowBox method was called nine times, using different parameter values:

Rectangle r1 = createShadowedBox(100, 10, 10,  5,  5, 10);
Rectangle r2 = createShadowedBox(100, 20, 20, 10, 10, 10);
Rectangle r3 = createShadowedBox(100, 30, 30, 15, 15, 10);
Rectangle r4 = createShadowedBox(100, 20, 20,  0,  0, 10);
Rectangle r5 = createShadowedBox(100, 20, 20,  0, 10, 10);
Rectangle r6 = createShadowedBox(100, 20, 20, 10,  0, 10);
Rectangle r7 = createShadowedBox(100, 20, 20, 10, 10,  0);
Rectangle r8 = createShadowedBox(100, 20, 20, 10, 10, 20);
Rectangle r9 = createShadowedBox(100, 20, 20, 10, 10, 50);

For the first set of three, the size and offset of the shadow was varied, in each, using the same values for width and height and for the x-offset and the y-offset. Thus, the first row of rectangles in the figure show various placements of the shadow below and to the right of the rectangles.

For the next set of three, the x-offset or y-offset was set to zero to demonstrate variations of the offset. And for the final set of three, the radius was varied. Notice that when the radius is set to 0, the shadow’s edges are crisp. With larger radius values, the shadow gets more blurry.

This figure shows how inner shadows work. For this figure, just one line of code was changed in the createShadowBox method: Instead of creating a DropShadow, an InnerShadow was created:

InnerShadow e = new InnerShadow();

As you can see, the InnerShadow class places the shadow on the inside of the rectangle rather than on the outside.

image2.jpg