JavaFX带阴影的分层布局

时间:2019-02-28 22:28:19

标签: java javafx ui-design

我正在学习JavaFX,并且正在尝试创建一个AnchorPane,它本身包含另外3个AnchorPane。当前,由于面板旁边的阴影,面板的阴影被隐藏了,我遇到了一个问题。因此,我需要一些有关如何解决此问题的建议。

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

我的代码:

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

2 个答案:

答案 0 :(得分:1)

子节点按添加顺序呈现,因此以相反的顺序添加就足够了:

<div class="container mt-5">
  <div class="row">
    <div class="col-lg-12 text-center">
      <input type="text" class="form">
    </div>
  </div>
</div>


<div class="container mt-5">
  <div class="row">
    <div class="col-lg-12 text-center">
      <input type="text" class="form">
    </div>
  </div>
</div>

<button class="btn btn-primary text-center" id="btn">SUBMIT</button>

答案 1 :(得分:0)

正如@VGR所说,子节点按照它们在子节点ObservableList中出现的顺序呈现。这意味着较高索引的子代将在较低索引的子代之上呈现。因此,示例中的其他节点已遮盖了阴影。由于您使用的是AnchorPane,它使用了开发人员设置的绝对位置,因此一个简单的解决方法是反转子级列表的顺序(如shown by VGR)。

如果您使用的布局也根据子级列表的顺序定位,例如HBox,则该解决方案将无法正常工作。您可以通过设置适当的转换来解决此问题,但不建议这样做。而是可以设置子级的viewOrder属性(在JavaFX 9中添加)。此属性:

  

定义此Node在其父对象中的渲染和拾取顺序。

     

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

     

父级将以降序children遍历其viewOrder。这意味着viewOrder较低的孩子将在viewOrder较高的孩子面前。如果两个孩子具有相同的viewOrder,则父级将按照它们在父级children列表中出现的顺序遍历它们。

由于您希望先前的子项呈现在后续子项之上,因此可以简单地将viewOrder设置为其在children列表中的索引。这是一个示例:

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

}

您提到您尝试过的解决方案之一是设置子级的Z顺序,但是它不起作用。为了使z坐标起作用,必须在创建Scene时启用深度缓冲。您可以通过修改上面的示例进行测试:

  • setViewOrder(i)更改为setTranslateZ(i)
  • new Scene(root)更改为new Scene(root, -1.0, -1.0, true)

这具有使用JavaFX 8的好处。