Создание групп определенных типов - PullRequest
0 голосов
/ 10 мая 2018

Я создал простой 3D-просмотрщик, используя SubScene и добавляя 3D-объекты в корневой элемент верхнего уровня.

public class Viewer extends AnchorPane {
   private final PerspectiveCamera camera = new PerspectiveCamera(true);
   private final Group root = new Group(camera)

   public Viewer() {
      SubScene scene = new SubScene(root, 300, 300, true, SceneAntialiasing.BALANCED);
   }

   public Group getRoot() {
      return root;
   }

Вызывая код, который пользователи Viewer могут затем получить рут, создать 3D-объекты и добавить их в корень. Это хорошо работает.

Однако я понял, что мне нужно логически разделить корень на три отдельные области из-за требований. Корень превратился в:

 private final Group cameraGroup = new Group(camera);
 private final Group lightGroup = new Group();
 private final Group objectsGroup = new Group();
 private final Group root = new Group(cameraGroup, lightGroup, objectsGroup);

Код вызова может добавить несколько камер, источников света, 3D-объектов через геттеры для вышеуказанных групп.

Вопрос: Если я предоставляю код вызова с геттерами для каждой группы, то код вызова также должен постоянно приводить узлы в группе к заданным типам (например, камеры в cameraGroup). Вызывающий код может также добавить негрупповые типы в Группу, поскольку многие вещи в JavaFX наследуются от общего базового типа Node, и именно с этим работает Группа.

Предоставление отдельных методов получения, установки, удаления и т. Д., Которые приводят группы к спискам / наблюдаемым спискам каждого типа, усложняет интерфейс.

Есть ли способ создать группу? группа определенного типа? Или есть другой способ сделать мой дизайн?

1 Ответ

0 голосов
/ 10 мая 2018

Group не является универсальным, поэтому прямого способа сделать то, что вы хотите, нет.

Однако вы можете хранить отдельные ObservableList с и выставлять их (вместо Group с), а также регистрировать слушателей с ними, чтобы синхронизировать списки дочерних узлов групп:

public class Viewer {

    private final PerspectiveCamera camera = new PerspectiveCamera();
    private final ObservableList<Camera> cameras = FXCollections.observableArrayList();
    private final Group cameraGroup = new Group();

    // etc

    public Viewer() {
        cameras.addListener((Change<? extends Camera> c) -> {
            while (c.next()) {
                if (c.wasAdded()) {
                    cameraGroup.getChildren().addAll(c.getAddedSubList());
                }
                if (c.wasRemoved()) {
                    cameraGroup.getChildren().removeAll(c.getRemoved());
                }
            }
        });

        cameras.add(camera);

        // etc

    }

    public ObservableList<Camera> getCameras() {
        return cameras ;
    }

}

Альтернативное решение (в основном то, которое вы описываете) состоит в том, чтобы определить конкретные addCamera() и removeCamera() и т. Д. Методы и предоставлять только неизменяемые списки:

public class Viewer {

    public final PerspectiveCamera camera = new PerspectiveCamera();

    public final Group cameraGroup = new Group(camera);

    public final void addCamera(Camera camera) {
        cameraGroup.getChildren().add(camera);
    }

    public boolean removeCamera(Camera camera) {
        return cameraGroup.getChildren().remove(camera);
    }

    public List<Camera> getCameras() {
        List<Camera> cameras = new ArrayList<>();
        for (Node n : cameraGroup.getChildren()) {
            cameras.add((Camera)n);
        }
        return Collections.unmodifiableList(cameras);
    }

    // etc...
}
...