Add dropShadow only to border of grid pane JavaFx 2.2

21,198

Solution 1

Use a StackPane and place your GridPane in it.

Style your StackPane with CSS to apply a background color, insets and a drop shadow.

See Drop Shadow in an undecorated Pane! JAVAFX for some sample CSS.

Here is a small standalone sample app (used Java 8b120 on OS X 10.9), to demonstrate the effect:

purple haze

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Shadowed extends Application {
    public static void main(String[] args) { launch(args); }

    @Override
    public void start(Stage stage) throws Exception {
        Label clear = new Label("Clear, with no shadow");
        StackPane shadowedPane = new StackPane(clear);
        shadowedPane.setStyle(
                "-fx-background-color: palegreen; " +
                "-fx-background-insets: 10; " +
                "-fx-background-radius: 10; " +
                "-fx-effect: dropshadow(three-pass-box, purple, 10, 0, 0, 0);"
        );
        shadowedPane.setPrefSize(200, 50);
        stage.setScene(new Scene(shadowedPane));
        stage.show();
    }
}

Addressing additional questions

Is CSS the only option?

No, this could be done in code instead of CSS, by using the DropShadow effect.

shadowedPane.setEffect(new DropShadow(10, Color.PURPLE));

Why does it work?

Because setting a background provides a clear edge to the node to which the shadow effect is applied.

Why does DropShadow work differently depending on if it's applied on a root node or a nested container?

There is no real differing behavior in the drop shadow processing between a root node or nested container. The drop shadow effect depends on whether the item having the effect applied has a transparent (or null) background or not. Note though that a root node usually fills a stage. So, if the root node has a non-transparent background color and no insets are supplied, then the shadow on the root node will not be seen as it will fall outside the visible area of the stage.


I'll offer a guess at what is happening. I think what the drop shadow effect is doing is calculating the exterior shape of the node, then applying the shadow to it. When that node has a background color, then the you will see the shadow of the node background, which is what is seen in the image supplied. If the node has no background color, then the edges of the nodes are calculated from the child nodes, so all of the children get shadows.

Now what happened is that between JavaFX 2.2 when the question was asked and JavaFX 8, the default theme for JavaFX moved from Caspian to Modena. With Caspian panes did not have any background color by default. However for Modena, panes do have a slight off-white background color by default. This means that the original poster's blurry text inside the grid pane won't occur by default in Java 8, as the GridPane will have a background which is shadowed, instead of interior text being shadowed. This can be verified via the running the following program and varying the commented out line for setting the stylesheet to Caspian:

import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Shadowed extends Application {
    public static void main(String[] args) { launch(args); }

    @Override
    public void start(Stage stage) throws Exception {
//        setUserAgentStylesheet(STYLESHEET_CASPIAN);
        Label clear = new Label("Clear, with no shadow");
        GridPane shadowedPane = new GridPane();
        shadowedPane.add(clear, 0, 0);
        GridPane.setHalignment(clear, HPos.CENTER);
        GridPane.setValignment(clear, VPos.CENTER);
        GridPane.setHgrow(clear, Priority.ALWAYS);
        GridPane.setVgrow(clear, Priority.ALWAYS);
        shadowedPane.setStyle(
//                "-fx-background-color: transparent; " +
//                "-fx-background-color: palegreen; " +
                "-fx-background-insets: 10; " +
                "-fx-background-radius: 10; "
        );
        shadowedPane.setPrefSize(200, 50);
        shadowedPane.setEffect(new DropShadow(10, Color.PURPLE));
        stage.setScene(new Scene(shadowedPane));
        stage.show();
    }
}

Solution 2

jewelsea's answer is correct, but please note that it does not work when

// explicitly transparent
-fx-background-color: transparent;

or

// effectively transparent
-fx-background-color: #FFFFFF00;

This can be really frustrating if you are trying to apply the drop shadow to the (Stack)Pane's entire bounding box area and not it's child contents! Setting a non-transparent background color works, but if you have many elements side by side or on top of each other (i.e. close together), you may see undesirable overlap effects with the drop shadows.

Share:
21,198
Zahid Khan
Author by

Zahid Khan

Software Engineer

Updated on July 09, 2022

Comments

  • Zahid Khan
    Zahid Khan almost 2 years

    Want to add drop shadow only to the border of Grid pane not to inner child elements

    enter image description here here is the image of screen showing the effect.