JavaFx 2.2中如何仅为网格面板的边框添加dropShadow?

7

想要只将投影添加到Grid面板的边框而不是内部子元素

enter image description here 这是屏幕上显示效果的图像。

2个回答

11

使用StackPane并将您的GridPane放置在其中。

使用CSS为StackPane设置样式以应用背景颜色、插入和阴影效果。

请参见Drop Shadow in an undecorated Pane! JAVAFX,了解一些示例CSS。

这里是一个小型独立的示例应用程序(在OS X 10.9上使用Java 8b120),演示了该效果:

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

回答额外的问题

CSS是唯一的选择吗?

不,也可以通过代码来实现,使用DropShadow效果。

shadowedPane.setEffect(new DropShadow(10, Color.PURPLE));
为什么这能起作用呢?因为设置背景色为节点提供了一个清晰的边界,应用阴影效果时也是以此为基础。
为什么在根节点或嵌套容器上应用 DropShadow 会有不同的效果呢?实际上,DropShadow 在根节点和嵌套容器之间并没有真正的不同行为。其效果取决于应用该效果的项是否具有透明(或空)背景。但请注意,根节点通常充满整个舞台。因此,如果根节点具有非透明背景颜色且未提供插入,则根节点上的阴影将看不到,因为它会落在舞台可见区域之外。
我猜这里发生的事情是,DropShadow 效果先计算出节点的外形,然后对其应用阴影。当该节点具有背景颜色时,您将看到节点背景的阴影,这就是所提供图片中所看到的。如果该节点没有背景颜色,则从子节点计算节点的边缘,因此所有子节点都会产生阴影。
现在发生的事情是,在 JavaFX 2.2 提出问题时和 JavaFX 8 之间,JavaFX 的默认主题从 Caspian 移动到 Modena。在 Caspian 中,默认情况下,窗格没有任何背景颜色。但是在 Modena 中,窗格默认具有略带灰白色的背景颜色。这意味着原帖中网格窗格中模糊的文本在 Java 8 中默认不会出现,因为 GridPane 将具有被阴影遮蔽的背景,而不是内部文本被阴影遮蔽。可以通过运行以下程序并变换设置样式表为 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();
    }
}

@jewslsea 在我的情况下不起作用,使用相同的技术创建具有2个子项和第二个是我的网格窗格的堆栈窗格,但仅应用于子项。 - Zahid Khan
添加了一个更简单的解决方案的示例。 - jewelsea
CSS是唯一的选择吗?它为什么有效?为什么DropShadow在应用于根节点或嵌套容器时会有不同的效果? - Itai

3
jewelsea的回答是正确的,但请注意,在以下情况下它无法正常工作:
// explicitly transparent
-fx-background-color: transparent;

或者

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

这可能会让人感到非常沮丧,如果您试图将投影应用于(Stack)Pane的整个边界框区域而不是其子内容!设置非透明背景颜色可以解决问题,但是如果您有许多元素并排或彼此叠放(即紧密在一起),则可能会看到投影产生的不良重叠效果。

1
是的...但是你怎么修复它? - dwb
这是正确的,但没有提供解决方案。 - FARS

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