JavaFX 3d SubScene в 2d сцене - PullRequest
2 голосов
/ 27 мая 2020

Я разрабатываю GUI для игры и хочу смешать 3D SubScene с 2D Pane в JavaFX. У меня есть группа под названием root3D, которая содержит все мои трехмерные объекты, уже установленные правильно, а затем я создаю панель, используя файл F XML, установленный с помощью JavaFX Scene Builder. Но ничего не появляется, и я вижу только свои 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();

F XML файл:

<?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>

No sign of the FXML Layout

РЕДАКТИРОВАТЬ: я обнаружил, что изменение размера подсцены, я можно увидеть элементы F XML. Судя по всему, их «прикрывает» субсцена. Кто-нибудь знает, как положить элементы F XML поверх подсцены, а не наоборот, как сейчас? The Subscene covers the FXML Layout I created

Ответы [ 2 ]

3 голосов
/ 27 мая 2020

Хотя вы нашли решение, я отправляю ответ в надежде прояснить ситуацию в отношении , почему вызов toBack() на вашем SubScene работает.

Z-порядок

Каждый Parent, от которого наследуются все макеты, может иметь одного или нескольких дочерних элементов. Если два (или более) дочерних элемента занимают одно и то же пространство в Parent, тогда один будет отображаться поверх другого. Какой ребенок нарисован поверх другого, определяется двумя вещами:

  1. Порядок дочерних элементов в списке Parent s children .
  2. ( Начиная с JavaFX 9) Значение свойства viewOrder каждого дочернего элемента относительно других дочерних элементов в том же Parent.

Z-порядок в JavaFX Вопросы и ответы более подробно.

Проблема в вашем коде

В вашем файле F XML описывается AnchorPane, у которого есть StackPane как единственный дочерний элемент. Это означает, что следующее:

AnchorPane pane = loader.load();

Дает вам AnchorPane с StackPane в его списке дочерних элементов с нулевым индексом. Затем вы сразу же добавляете свой SubScene, используя:

pane.getChildren().add(subScene);

Метод add, который вы используете, добавляет элемент в конец списка. Это означает, что список дочерних элементов AnchorPane следующий:

  1. StackPane
  2. SubScene

Так как SubScene приходит после StackPane первый отображается поверх последнего.

Ваше решение

Решение, которое вы выбрали, - вызвать toBack() на вашем SubScene после добавления его в AnchorPane. Вот документация этого метода:

Перемещает этот Node на задний план его родственных узлов с точки зрения z-порядка. Это достигается перемещением этого Node на первую позицию в его родительском содержимом ObservableList. Эта функция не действует, если этот Node не является частью группы.

Другими словами, после того, как вы вызываете этот метод, список дочерних элементов AnchorPane становится следующим:

  1. SubScene
  2. 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>
    
2 голосов
/ 27 мая 2020

Как косвенно указал @Slaw, мне нужно было установить Subscene.toBack (), чтобы установить правильный Z-порядок в моей сцене. Большое спасибо! Читая о Subscenes, я ничего не нашел об этом, так что надеюсь, что это может помочь некоторым новичкам в 3D в будущем. конечный результат

...