二维场景中的JavaFX三维子场景
我正在为一个游戏开发一个GUI,我想在JavaFX中混合一个3D子场景和一个2D窗格。我有一个名为root3D的组,其中包含已正确设置的所有3d对象,然后我将使用通过JavaFX场景生成器设置的FXML文件创建一个窗格。但是什么都没有显示,我只能看到我的3D对象二维场景中的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 =
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不起作用。从你的照片上看,我以为你左边有一个面板。