如何创建一个JavaFX透明的窗口边框,仅有阴影?

14

我已经阅读了许多关于透明度和阴影的问题,但我认为没有看到针对这个特定问题的解决方法。

我能够成功地创建一个既具有透明度又具有阴影的窗口,但我无法弄清楚如何使颜色阴影不影响透明度颜色。

例如,以下代码创建了一个具有灰色透明度和红色投影的窗口。然而,红色会影响主窗口的透明度,而我只想让阴影延伸到窗口边框外面。

所以我的问题是:

enter image description here

但我想要的是:
(手动编辑的图像)

enter image description here

有什么办法可以做到这一点吗?

我测试用的代码:

@Override
public void start(Stage stage) throws Exception {
    stage.initStyle(StageStyle.TRANSPARENT);

    StackPane stackPane = new StackPane();

    stackPane.setStyle(
        "-fx-background-color: rgba(255, 255, 255, 0.5);" +
        "-fx-effect: dropshadow(gaussian, red, 50, 0, 0, 0);" +
        "-fx-background-insets: 50;"
    );

    Scene scene = new Scene(stackPane, 450, 450);
    scene.setFill(Color.TRANSPARENT);

    stage.setScene(scene);

    stage.show();
}
1个回答

26

我一直很好奇如何实现这样的阴影效果,其中阴影效果不会透过半透明顶部内容显示出来。

我想出的解决方案是在阴影上使用裁剪,这样它只会显示在被其投射阴影的半透明内容之外。

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

相关

这个答案是对一些关于半透明窗口和面板的其他问题的跟进,其中有多个部分,我没有实现其中一个关于如何在半透明窗口上获得光晕阴影效果的问题?(这个问题)


谢谢,这个可行。有什么办法可以使红色阴影真正透明,以便单击阴影时可以将焦点放在窗口后面的应用程序上吗? - dejuknow
在这里创建了一个新问题:http://stackoverflow.com/questions/25650491/how-to-cause-clicking-on-transparent-areas-to-focus-on-applications-the-javafx-w。谢谢! - dejuknow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接