Хотя вы нашли решение, я отправляю ответ в надежде прояснить ситуацию в отношении , почему вызов toBack()
на вашем SubScene
работает.
Z-порядок
Каждый Parent
, от которого наследуются все макеты, может иметь одного или нескольких дочерних элементов. Если два (или более) дочерних элемента занимают одно и то же пространство в Parent
, тогда один будет отображаться поверх другого. Какой ребенок нарисован поверх другого, определяется двумя вещами:
- Порядок дочерних элементов в списке
Parent
s children . - ( Начиная с JavaFX 9) Значение свойства
viewOrder
каждого дочернего элемента относительно других дочерних элементов в том же Parent
.
Z-порядок в JavaFX Вопросы и ответы более подробно.
Проблема в вашем коде
В вашем файле F XML описывается AnchorPane
, у которого есть StackPane
как единственный дочерний элемент. Это означает, что следующее:
AnchorPane pane = loader.load();
Дает вам AnchorPane
с StackPane
в его списке дочерних элементов с нулевым индексом. Затем вы сразу же добавляете свой SubScene
, используя:
pane.getChildren().add(subScene);
Метод add
, который вы используете, добавляет элемент в конец списка. Это означает, что список дочерних элементов AnchorPane
следующий:
StackPane
SubScene
Так как SubScene
приходит после StackPane
первый отображается поверх последнего.
Ваше решение
Решение, которое вы выбрали, - вызвать toBack()
на вашем SubScene
после добавления его в AnchorPane
. Вот документация этого метода:
Перемещает этот Node
на задний план его родственных узлов с точки зрения z-порядка. Это достигается перемещением этого Node
на первую позицию в его родительском содержимом ObservableList
. Эта функция не действует, если этот Node
не является частью группы.
Другими словами, после того, как вы вызываете этот метод, список дочерних элементов AnchorPane
становится следующим:
SubScene
StackPane
Вот почему SubScene
теперь отображается под StackPane
, потому что вы изменили порядок дочерних элементов.
Обратите внимание, что метод toBack()
является частью класса Node
, а не SubScene
. Последнее унаследовано от первого. Я поднимаю это, чтобы указать, что проблема, с которой вы столкнулись, не связана с спецификацией c до SubScene
или даже смешением 2D и 3D графиков сцены вместе. И ваш StackPane
, и ваш SubScene
являются частью 2D Scene
(т.е. без буферизации глубины), что означает, что их z-порядок регулируется исключительно тем, что обсуждалось выше *. Тот факт, что SubScene
является трехмерным (т.е. включена буферизация глубины), не имеет отношения к рассматриваемой проблеме; этот факт влияет только на потомков указанного SubScene
.
* В 3D-сцене значение z-координаты узла становится актуальным.
Другие решения
Вот несколько других подходов, которые можно использовать для решения вашей проблемы:
Добавьте SubScene
в начало список дочерних элементов AnchorPane
:
pane.getChildren().add(0, subScene);
Если вы используете JavaFX 9+, установите для свойства viewOrder
элемента SubScene
значение меньшее, чем у свойство AnchorPane
(по умолчанию значение этого свойства 0
):
subScene.setViewOrder(-1);
Определите свой SubScene
в файле F XML перед StackPane
(обратите внимание, что этот подход требует использования контроллера F XML ):
<?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>