带阴影的JavaFX分层布局

带阴影的JavaFX分层布局,java,javafx,ui-design,Java,Javafx,Ui Design,我正在学习JavaFX,我正在尝试创建一个AnchorPane,其中包含了另外3个AnchorPanes。目前,我有一个问题,面板的阴影是隐藏的,因为它旁边的面板。所以我需要一些关于如何解决这个问题的建议 我试图在它们之间建立一个距离,但我可以看到后面有一个白色的层。我试图改变图层的z顺序,但似乎不起作用,所以在两个小时不知道该做什么后,我在这里问。也许有人知道 我的代码: DropShadow dropShadow2; AnchorPane iconPane, menuPane

我正在学习JavaFX,我正在尝试创建一个
AnchorPane
,其中包含了另外3个
AnchorPane
s。目前,我有一个问题,面板的阴影是隐藏的,因为它旁边的面板。所以我需要一些关于如何解决这个问题的建议

我试图在它们之间建立一个距离,但我可以看到后面有一个白色的层。我试图改变图层的z顺序,但似乎不起作用,所以在两个小时不知道该做什么后,我在这里问。也许有人知道

我的代码:

    DropShadow dropShadow2;
    AnchorPane iconPane, menuPane, viewPane;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage){
        dropShadow2 = new DropShadow();
        dropShadow2.setOffsetX(6.0);
        dropShadow2.setOffsetY(4.0);

        //Main layout
        AnchorPane main_layout = new AnchorPane();

        //Icon layout (left)
        setUpIconLayout();

        //Menu layout (center)
        setUpMenuLayout();

        //View layout (right)
        setUpViewLayout();

        main_layout.getChildren().addAll(iconPane, menuPane, viewPane);

        Scene scene = new Scene(main_layout, 1000, 600);
        primaryStage.setTitle("Delivery System Database");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void setUpIconLayout() {

        iconPane = new AnchorPane();
        iconPane.setPrefSize(50,600);
        String hexColor_left = "D64550";
        iconPane.setStyle("-fx-background-color: #" + hexColor_left);
        iconPane.setEffect(dropShadow2);
    }

    private void setUpMenuLayout() {

        menuPane = new AnchorPane();
        menuPane.setPrefSize(200,600);
        String hexColor_mid = "EA9E8D";
        menuPane.setStyle("-fx-background-color: #" + hexColor_mid);
        menuPane.setEffect(dropShadow2);
        menuPane.setTranslateX(50);
    }

    private void setUpViewLayout() {
        viewPane = new AnchorPane();
        viewPane.setPrefSize(700,600);
        String hexColor_right = "DAEFB3";
        viewPane.setStyle("-fx-background-color: #" + hexColor_right);
        viewPane.setEffect(dropShadow2);
        viewPane.setTranslateX(250);
    }
}

子节点按添加顺序渲染,因此按相反顺序添加就足够了:

main_layout.getChildren().addAll(viewPane, menuPane, iconPane);

子节点按添加顺序渲染,因此按相反顺序添加就足够了:

main_layout.getChildren().addAll(viewPane, menuPane, iconPane);

正如@VGR所说,子节点是按照它们在子
ObservableList
中出现的顺序呈现的。这意味着索引较高的子对象将呈现在索引较低的子对象之上。因此,阴影被示例中的其他节点覆盖。由于您使用的是
AnchorPane
,它使用开发人员设置的绝对位置,因此一个简单的修复方法是颠倒子列表(如图所示)的顺序

如果您使用的布局也基于子列表的顺序定位其子项,例如
HBox
,则该解决方案将无法正常工作。您可以通过设置适当的转换来解决此问题,但不建议这样做。相反,您可以设置在JavaFX 9-1中添加的属性。此属性:

定义此
节点在其父节点中的呈现和拾取顺序

此属性用于更改父节点内节点的渲染和拾取顺序,而无需重新排序父节点的子列表。例如,这可以用作实现透明度排序的更有效的方法。为此,应用程序可以将每个节点的
viewOrder
值指定给该节点与查看器之间的计算距离

父对象将以递减的查看顺序遍历其子对象。这意味着具有较低视图顺序的子对象将位于具有较高视图顺序的子对象的前面。如果两个子项具有相同的
视图顺序
,则父项将按照它们在父项的
子项
列表中出现的顺序遍历它们

由于您希望在后续子对象上方呈现先前的子对象,因此只需将
视图顺序设置为
子对象
列表中的索引即可。下面是一个例子:

import java.util.stream.DoubleStream;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {
        HBox root = new HBox(createRegions(50.0, 200.0, 700.0));
        root.setPadding(new Insets(0.0, 75.0, 0.0, 0.0));
        for (int i = 0; i < root.getChildren().size(); i++) {
            root.getChildren().get(i).setViewOrder(i);
        }
        primaryStage.setScene(new Scene(root));
        primaryStage.setTitle("ViewOrder Example");
        primaryStage.show();
    }

    private Region[] createRegions(double... prefWidths) {
        return DoubleStream.of(prefWidths).mapToObj(prefWidth -> {
            Region region = new Region();
            region.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
            region.setPrefSize(prefWidth, 600.0);
            region.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
            region.setEffect(new DropShadow(BlurType.THREE_PASS_BOX, Color.BLACK, 10.0, 0.0, 6.0, 4.0));
            region.setBackground(new Background(new BackgroundFill(Color.WHITE, null, null)));
            return region;
        }).toArray(Region[]::new);
    }

}
import java.util.stream.DoubleStream;
导入javafx.application.application;
导入javafx.geometry.Insets;
导入javafx.scene.scene;
导入javafx.scene.effect.BlurType;
导入javafx.scene.effect.DropShadow;
导入javafx.scene.layout.Background;
导入javafx.scene.layout.BackgroundFill;
导入javafx.scene.layout.HBox;
导入javafx.scene.layout.Region;
导入javafx.scene.paint.Color;
导入javafx.stage.stage;
公共类主扩展应用程序{
@凌驾
公共无效开始(阶段primaryStage){
HBox根=新的HBox(createRegions(50.02000.0700.0));
根设置填充(新的插入(0.0,75.0,0.0,0.0));
for(int i=0;i{
区域=新区域();
region.setMinSize(region.USE\u PREF\u SIZE,region.USE\u PREF\u SIZE);
region.setPrefSize(prefWidth,600.0);
region.setMaxSize(region.USE\u PREF\u SIZE,region.USE\u PREF\u SIZE);
region.setEffect(新的DropShadow(BlurType.THREE_PASS_BOX,Color.BLACK,10.0,0.0,6.0,4.0));
区域.背景(新背景(新背景填充(颜色.白色,空,空));
返回区;
}).toArray(地区[]::新建);
}
}

您提到您尝试的解决方案之一是设置孩子们的Z顺序,但它不起作用。为了将
z
坐标设置为有效,必须在创建
场景时启用深度缓冲。您可以通过修改上述示例来测试这一点:

  • setViewOrder(i)
    更改为
    setTranslateZ(i)
  • 新场景(root)
    更改为
    新场景(root,-1.0,-1.0,true)

使用JavaFX 8有好处。

正如@VGR所说,子节点按照它们在子节点
可观察列表中出现的顺序呈现。这意味着索引较高的子对象将呈现在索引较低的子对象之上。因此,阴影被示例中的其他节点覆盖。由于您使用的是
AnchorPane
,它使用开发人员设置的绝对位置,因此一个简单的修复方法是颠倒子列表(如图所示)的顺序

如果您使用的布局也基于子列表的顺序定位其子项,例如
HBox
,则该解决方案将无法正常工作。您可以通过设置适当的转换来解决此问题,但不建议这样做。相反,您可以设置在JavaFX 9-1中添加的属性。此属性:

定义此
节点在其父节点中的呈现和拾取顺序

此属性用于更改父节点内节点的渲染和拾取顺序,而无需重新排序父节点的子列表。例如,这可以用作实现透明度排序的更有效的方法。为此,应用程序可以将每个节点的
viewOrder
值分配给