How do I create a JavaFX transparent stage with shadows on only the border?

前端 未结 1 471
梦如初夏
梦如初夏 2020-12-02 16:30

I\'ve read through many questions on transparency and shadows, but I don\'t think I\'ve seen this specific issue addressed.

I\'m able to successfully create a window

相关标签:
1条回答
  • 2020-12-02 16:49

    I've been kind of curious for a while about how to achieve such a shadow effect where the shadow effect does not show through underneath translucent top content.

    The solution I came up with was to use clipping on the shadow so that it only displays outside of the translucent content that it is shadowing.

    bloodstage

    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.layout.*;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.*;
    import javafx.stage.*;
    import org.scenicview.ScenicView;
    
    // Java 8 code
    public class ClippedShadow extends Application {
    
        private static final int shadowSize = 50;
    
        @Override public void start(final Stage stage) {
            stage.initStyle(StageStyle.TRANSPARENT);
    
            StackPane stackPane = new StackPane(createShadowPane());
            stackPane.setStyle(
                    "-fx-background-color: rgba(255, 255, 255, 0.5);" +
                    "-fx-background-insets: " + shadowSize + ";"
            );
    
            Scene scene = new Scene(stackPane, 450, 450);
            scene.setFill(Color.TRANSPARENT);
            stage.setScene(scene);
            stage.show();
        }
    
        // Create a shadow effect as a halo around the pane and not within
        // the pane's content area.
        private Pane createShadowPane() {
            Pane shadowPane = new Pane();
            // a "real" app would do this in a CSS stylesheet.
            shadowPane.setStyle(
                    "-fx-background-color: white;" +
                    "-fx-effect: dropshadow(gaussian, red, " + shadowSize + ", 0, 0, 0);" +
                    "-fx-background-insets: " + shadowSize + ";"
            );
    
            Rectangle innerRect = new Rectangle();
            Rectangle outerRect = new Rectangle();
            shadowPane.layoutBoundsProperty().addListener(
                    (observable, oldBounds, newBounds) -> {
                        innerRect.relocate(
                                newBounds.getMinX() + shadowSize,
                                newBounds.getMinY() + shadowSize
                        );
                        innerRect.setWidth(newBounds.getWidth() - shadowSize * 2);
                        innerRect.setHeight(newBounds.getHeight() - shadowSize * 2);
    
                        outerRect.setWidth(newBounds.getWidth());
                        outerRect.setHeight(newBounds.getHeight());
    
                        Shape clip = Shape.subtract(outerRect, innerRect);
                        shadowPane.setClip(clip);
                    }
            );
    
            return shadowPane;
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    Related

    This answer is kind of a follow on to some other questions on translucent windows and panes which had multiple parts, one of which I did not get around to implementing regarding: How to get a halo drop shadow effect on a translucent window? (this question)

    • JavaFX effect on background
    • Frosted Glass Effect in JavaFX?
    0 讨论(0)
提交回复
热议问题