二维场景中的JavaFX三维子场景

二维场景中的JavaFX三维子场景,java,javafx,scenebuilder,Java,Javafx,Scenebuilder,我正在为一个游戏开发一个GUI,我想在JavaFX中混合一个3D子场景和一个2D窗格。我有一个名为root3D的组,其中包含已正确设置的所有3d对象,然后我将使用通过JavaFX场景生成器设置的FXML文件创建一个窗格。但是什么都没有显示,我只能看到我的3D对象 PerspectiveCamera camera = new PerspectiveCamera(true); camera.setTranslateZ(-30); Group root3D =

我正在为一个游戏开发一个GUI,我想在JavaFX中混合一个3D子场景和一个2D窗格。我有一个名为root3D的组,其中包含已正确设置的所有3d对象,然后我将使用通过JavaFX场景生成器设置的FXML文件创建一个窗格。但是什么都没有显示,我只能看到我的3D对象

       PerspectiveCamera camera = new PerspectiveCamera(true);
       camera.setTranslateZ(-30);
       Group root3D = new Group(model1,model2,model3); //various 3d models I imported
       SubScene subScene = new SubScene(root3D, 1280, 700, true,SceneAntialiasing.BALANCED);
       subScene.setCamera(camera);
       FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/file.fxml"));
       AnchorPane pane = loader.load();
       pane.getChildren().add(subScene);
       Scene scene = new Scene(pane);
       primaryStage.setScene(scene);
       primaryStage.setResizable(false);
       primaryStage.show();

FXML文件:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.text.Font?>

<AnchorPane prefHeight="700.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <StackPane prefHeight="150.0" prefWidth="200.0">
         <children>
            <ImageView fitHeight="214.0" fitWidth="169.0" pickOnBounds="true" preserveRatio="true">
               <image>
                  <Image url="@../Sprite/Cards/Small/podium-characters-Poseidon.png" />
               </image>
            </ImageView>
            <TextField prefHeight="62.0" prefWidth="274.0" text="APOLLO">
               <font>
                  <Font name="Trebuchet MS Bold Italic" size="22.0" />
               </font>
            </TextField>
         </children>
      </StackPane>
   </children>
</AnchorPane>

编辑:我发现调整子场景的大小,可以看到FXML元素。显然,它们正被亚新世“覆盖”。有人知道如何将FXML元素放置在子场景的顶部,而不是像现在这样的相反位置吗?

正如@Slaw间接指出的,我需要设置Subscene.toBack()以在场景中设置正确的Z顺序。非常感谢你!在阅读有关子场景的文章时,我没有发现任何关于它的信息,所以我希望这能帮助一些3d初学者。

虽然您已经找到了解决方案,但我发布了一个答案,希望能让您更清楚地了解在
子场景上调用
toBack()
的原因

Z阶 所有布局继承自的每个父级可以有一个或多个子级。如果两个(或多个)子对象在父对象中占据相同的空间,则其中一个将在另一个上渲染。哪一个孩子被另一个孩子所吸引是由两件事决定的:

  • 父项中子项的顺序
  • (自JavaFX9以来)每个子级的属性相对于同一父级中其他子级的值
  • 问答会更加详细

    代码中的问题 FXML文件描述了一个
    AnchorPane
    ,它的唯一子项是
    StackPane
    。这意味着:

    AnchorPane pane=loader.load();
    
    为您提供一个
    AnchorPane
    ,其子列表中的第0个索引处有一个
    StackPane
    。然后立即使用以下方法添加
    子场景

    pane.getChildren().add(子场景);
    
    您使用的
    add
    方法将元素追加到列表的末尾。这意味着,
    AnchorPane
    的子列表的顺序是:

  • StackPane
  • SubScene
  • 由于
    子场景
    位于
    堆栈窗格
    之后,因此前者呈现在后者之上

    你的解决方案 您选择的解决方案是在将
    主播添加到
    主播
    后,在
    子场景
    上调用
    toBack()
    。下面是该方法的示例:

    按z顺序将此
    节点
    移动到其同级节点的后面。这是通过将此
    节点
    移动到其父级内容中的第一个位置来实现的
    可观察列表
    。如果此
    节点
    不是组的一部分,则此函数无效

    换句话说,调用该方法后,
    AnchorPane
    的子列表的顺序变为:

  • SubScene
  • StackPane
  • 这就是为什么
    子场景现在呈现在
    堆栈窗格下的原因,因为您更改了子场景的顺序

    请注意,
    toBack()
    方法是
    节点
    类的一部分,而不是
    子场景
    。后者继承了前者。我提出这一点是为了指出,您遇到的问题并不是特定于
    子场景
    ,甚至不是将2D和3D场景图混合在一起。您的
    堆栈窗格
    子场景
    都是2D
    场景
    的一部分(即没有深度缓冲),这意味着它们的z顺序完全由上面讨论的内容决定*。
    子场景
    为3D(即启用深度缓冲)这一事实与当前问题无关;这一事实只影响所述
    亚场景的后代

    *在3D场景中,节点的z坐标变得相关

    其他解决方案 以下是一些可以用来解决问题的其他方法:

    • 子场景
      添加到
      AnchorPane
      的子列表的开头:

      pane.getChildren().add(0,子场景);
      
    • 如果您使用的是JavaFX 9+,请将
      子场景的
      viewOrder
      属性设置为小于
      AnchorPane
      属性的值(默认情况下,该属性的值为
      0
      ):

      subScene.setViewOrder(-1);
      
    • 堆栈窗格
      之前的FXML文件中定义您的
      子场景
      (注意此方法需要使用):

      
      

    请参阅。不幸的是,你似乎没有提供足够的信息让我更具体。如果需要更多帮助,请考虑提供。您可能还想签出
    StackPane
    。另外,从您对
    pane.setCenter(subScene)
    的调用中,我假设
    pane
    引用了
    BorderPane
    。如果这是正确的,那么您应该删除对
    pane.getChildren().add(subScene)
    的调用。当涉及到诸如
    BorderPane
    之类的布局时,您不应该直接与子列表交互。请确保您的FXML根节点是
    HBox
    BorderPane
    <代码>边框窗格
    可能是首选。将
    子基因设置为
    center`或
    right
    。显然,我编辑了这个问题,但有些编辑没有显示出来,因此代码是两者的混合,也让我感到困惑。我修好了。我的FXML根目录目前是一个锚窗格;这就是问题所在吗,塞德里克?我尝试将其设置为StackPane,但结果似乎是一样的。BorderPane不起作用。从你的照片上看,我以为你左边有一个面板。