ano*_*aco 3 java javafx scenebuilder
我正在为游戏开发 GUI,我想在 JavaFX 中混合 3D SubScene 和 2D Pane。我有一个名为 root3D 的组,其中包含已正确设置的所有 3d 对象,然后我使用通过 JavaFX Scene Builder 设置的 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();
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
编辑:我发现调整子场景的大小,我可以看到 FXML 元素。显然他们被场景“覆盖”了。有谁知道如何将 FXML 元素放置在子场景之上,而不是像现在这样相反?

尽管您已经找到了解决方案,但我发布了一个答案,希望能让事情更清楚地了解为什么调用toBack()您的SubScene作品。
所有布局都继承自每个Parent,可以有一个或多个子级。如果两个(或更多)子元素占据同一空间,则其中Parent一个将渲染在另一个之上。哪个孩子被吸引到另一个孩子身上取决于两个因素:
JavaFX Q&A 中的Z顺序有更多详细信息。
您的 FXML 文件描述了 ,AnchorPane其中 是StackPane其唯一的子项。这意味着:
AnchorPane pane = loader.load();
Run Code Online (Sandbox Code Playgroud)
为您提供一个在其子列表中的第零个索引处AnchorPane带有a 的对象。StackPane然后您立即添加您的SubScene使用:
pane.getChildren().add(subScene);
Run Code Online (Sandbox Code Playgroud)
add您使用的方法将元素追加到列表的末尾。这意味着AnchorPane的子列表的顺序是:
StackPaneSubScene由于SubScene出现在前者之后,因此StackPane前者呈现在后者之上。
您选择的解决方案是将其添加toBack()到. 这是该方法的文档:SubSceneAnchorPane
Node按照 z 顺序将其移动到其同级节点的后面。这是通过将其移至Node其父级 content 中的第一个位置来实现的ObservableList。Node如果该函数不属于某个组,则此函数无效。
换句话说,调用该方法后, 的AnchorPane子列表的顺序变为:
SubSceneStackPane这就是为什么SubScene现在将 呈现在 下方StackPane,因为您更改了子项的顺序。
请注意,该toBack()方法是类的一部分Node,而不是SubScene。后者继承了前者。我提出这一点是为了指出您遇到的问题并不是特定于SubScene2D 和 3D 场景图,甚至不是将 2D 和 3D 场景图混合在一起。yourStackPane和 yourSubScene都是 2D 的一部分Scene(即没有深度缓冲),这意味着它们的 z 顺序仅受上面讨论的内容控制*。事实上,SubScene3D(即启用深度缓冲)与当前的问题无关;该事实仅影响said 的后代SubScene。
* 在 3D 场景中,节点的 z 坐标变得相关。
以下是一些可用于解决您的问题的其他方法:
添加到 的子列表SubScene的开头:AnchorPane
pane.getChildren().add(0, subScene);
Run Code Online (Sandbox Code Playgroud)如果您使用的是 JavaFX 9+,请将 的viewOrder属性设置SubScene为小于 的AnchorPane属性(默认情况下,该属性的值为0):
subScene.setViewOrder(-1);
Run Code Online (Sandbox Code Playgroud)SubScene在 FXML 文件中定义StackPane(注意此方法需要使用FXML 控制器):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.Group?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.SceneAntialiasing?>
<?import javafx.scene.SubScene?>
<?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>
<!-- Define the SubScene before the StackPane -->
<SubScene fx:id="subScene" width="1280" height="700" depthBuffer="true">
<antiAliasing>
<SceneAntialiasing fx:constant="BALANCED"/>
</antiAliasing>
<!--
Unfortunately, as far as I can tell, you can't set your PerspectiveCamera in FXML because you
want 'fixedEyeAtCameraZero' to be true. That property can only be set during construction but
the constructor with that parameter does not annotate said parameter with @NamedArg, thus the
FXMLLoader can't see it. And the no-arg constructor sets the value to false, not true. This
means you have to inject the SubScene into your controller and add the PerspectiveCamera in
code.
-->
<root>
<!-- Inject the root into the controller in order to add your models to it in code -->
<Group fx:id="root3D"/>
</root>
</SubScene>
<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>
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
1313 次 |
| 最近记录: |