Intereting Posts
Как получить сгенерированные ключи из пакетной вставки JDBC в Oracle? С JUnit 5, как обмениваться информацией в «ExtensionContext.Store» между тестовыми экземплярами? Как правильно выровнять кнопку на панели инструментов Java FX Я должен дважды щелкнуть кнопку, чтобы она работала Как сделать вывод в разных столбцах? Вы действительно используете свой обратный домен для именования пакетов в java? JFreeChart: Dispay координаты мыши рядом с мышью в качестве подсказок (при перемещении мыши) Миграция в Spring Boot 2 – Безопасность Кодированный пароль не похож на BCrypt Допустимо ли использовать исключения вместо подробных нуль-чеков? Eclipse Indigo набирает отставание от OS X Lion Является ли платформенный механизм управления версиями наиболее необходимой функцией Java? java generics и annotations, не поддерживаемые в версии 1.3 (интеграция travis) Как перебирать членов classа? Как объединить два или несколько файлов изображений TIFF в одно многостраничное изображение TIFF в JAVA Что такое объекты первого classа в Java и C #?

Как инициализировать controllerы JavaFX с одним и тем же объектом модели?

сценарий

Я создаю графический интерфейс, в котором несколько представлений ссылаются на один и тот же объект модели.

Что я

В Swing, если я хочу, чтобы все представления ссылались на одну и ту же модель, я передал бы модель в конструктор.

Что я сейчас делаю

В JavaFX я прохожу модель вокруг, имея метод setter в представлениях / controllerах (menubars, split panes, tabs, …) после загрузки каждого представления / controllerа. Я нахожу это очень липким и громоздким. Кроме того, я считаю, что это не сработает, потому что в определенных ситуациях мне нужна модель, которая уже существует в controllerе, прежде чем инициализируются некоторые из виджетов controllerа.

Альтернативные варианты

(Примечание. Я ссылаюсь на эти вопросы с помощью stackoverflow:

  • Javafx 2.0 How-to Application.getParameters () в файле Controller.java
  • Передача параметров JavaFX FXML
  • Несколько FXML с controllerами, общий объект
  • Передача параметров controllerу при загрузке FXML )

  • Внедрение зависимости

    • Я просмотрел этот сайт, http://www.zenjava.com/2011/10/23/javafx-2-0-fxml-and-spring/ , и я немного поглядел на google Guice, но я не Нет простого способа упростить отображение каждого вида / controllerа JavaFX одного и того же объекта модели. Казалось, что инъекция вводит другую модель для каждого вида / controllerа.
  • Сохранение объекта модели как общедоступной статической переменной

    • Это вариант, но на данный момент мне не нравится идея открытой публичной статической модели. Очевидно, я могу сделать его частной статической переменной и иметь геттеры и сеттеры, но мне тоже не нравится эта идея.
  • Передача параметров от вызывающего к controllerу

    • Я хочу, чтобы каждый controller загружал себя в свой конструктор, и я хочу, чтобы каждый пользовательский controller автоматически вводился в его родительский controller. Например, вкладка обзора карты загружается следующим образом:

      public CardOverviewTab() { FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("card_overview_tab.fxml")); fxmlLoader.setRoot(content); fxmlLoader.setController(this); try { fxmlLoader.load(); } catch (Exception e) { e.printStackTrace(); } } 
    • И controller SingleGameSetup имеет вкладку обзора карты, автоматически вводимую в переменную:

       public class SingleGameSetupController extends AnchorPane { @FXML private CardOverviewTab cardOverviewTab; // Rest of the class } 
    • И часть fxml, содержащая вкладку обзора карты, выглядит следующим образом:

        
    • Таким образом, мне не нужно беспокоиться о ручной загрузке controllerа, но у меня все еще есть проблема с настройкой модели.

  • Установка controllerа на FXMLLoader

    • Этот параметр похож на то, к чему я привык, передавая модель в качестве параметра в конструктор, но по-прежнему возникает проблема загрузки controllerов вручную с помощью FXMLLoader.
  • Автобус событий

    • Я не слишком много читал в этом, но из того, что я прочитал, автобус событий кажется неактивным и устаревшим.
  • одиночка

    • Это похоже на наличие публичной статической ссылки на объект модели, который могут получить controllerы, но опять же я ищу лучшее решение. Кроме того, я не хочу синглтонную модель.

Что я ищу

Есть ли способ передать объект модели вокруг менее громоздким способом? Я ищу способ, который так же прост, как передать модель конструктору, но я не хочу иметь дело с ручными controllerами загрузки через FXMLLoader или устанавливать модель после загрузки controllerов. Возможно, лучший способ выбрать class для извлечения модели, но я прошу на всякий случай, если есть лучший способ.

Обновить

В дополнение к afterburner.fx, также проверка Gluon Ignite :

Gluon Ignite позволяет разработчикам использовать в своих приложениях JavaFX популярные платформы для внедрения зависимостей, в том числе внутри своих controllerов FXML. Gluon Ignite создает общую абстракцию над несколькими популярными структурами инъекций зависимостей (в настоящее время Guice, Spring и Dagger), но мы планируем добавить больше, поскольку спрос становится очевидным). При полной поддержке JSR-330 Gluon Ignite делает использование инъекций зависимостей в приложениях JavaFX тривиальным.

Инъекция объектов модели в controllerы также осуществляется через @Inject, аналогично afterburner.fx.

Предлагаемый подход

Поскольку вы, похоже, ищете инфраструктуру внедрения зависимостей, я считаю, что ваш лучший вариант – использовать инфраструктуру afterburner.fx .

afterburner.fx обеспечивает способ ввода объектов модели в ваши controllerы JavaFX, используя стандартную аннотацию Java @Inject .

Альтернативные системы впрыскивания

Весна большая и сложная, и, если вам не нужно много других функций для вашего приложения, не следует рассматривать из-за ее сложности.

Guice намного проще Spring и разумного выбора, если вам нужна инфраструктура инъекций зависимостей с многочисленными функциями, такими как classы поставщиков. Но из-за этого вам не нужны все функции, которые предоставляет Guice, поскольку вы просто хотите передать отдельные экземпляры объектов в своем приложении, не просматривая их явно.

Итак, попробуйте afterburner.fx и посмотрите, подходит ли оно вашим потребностям.

Образец кода afterburner.fx

Ниже приведен пример ввода экземпляра модели ( NotesStore ) в controller с использованием NotesStore . Образец напрямую копируется из документации afterburner.fx .

 import com.airhacks.afterburner.views.FXMLView; public class NoteListView extends FXMLView { //usually nothing to do, FXML and CSS are automatically //loaded and instantiated } public class AirpadPresenter implements Initializable { @Inject // injected by afterburner, zero configuration required NotesStore store; @FXML // injected by FXML AnchorPane noteList; @Override public void initialize(URL url, ResourceBundle rb) { //view constructed from FXML NoteListView noteListView = new NoteListView(); //fetching and integrating the view from FXML Parent view = noteListView.getView(); this.noteList.getChildren().add(view); } } 

followme.fx – базовое примерное приложение, демонстрирующее, как использовать afterburner.fx. У меня было несколько проблем с получением followme.fx, запущенного прямо из коробки из-за несовместимости зависимости Maven, поэтому я разветвил его код и исправил некоторые проблемы, которые мешали мне использовать его из коробки.

Ответы на дополнительные вопросы из комментариев

Итак, из примера NoteStore, вы говорите, что все, что мне нужно сделать, это добавить зависимость структуры Afterburner и поместить @Inject в мою переменную модели?

Нет, вам также нужно создать связанный class, который расширяет FXMLView и создает его с помощью нового вызова (аналогично тому, как NotesListView создается в примере кода выше). Если вы заинтересованы в продолжении изучения структуры afterburner.fx, используйте проект followme.fx как основу, потому что он обеспечивает полный исходный код для очень простого исполняемого примера с использованием фреймворка.

Я попробовал google guice и заставил его работать. , , вы увидите, что в конструкторе объект настроек игры вводится вручную.

Я не думаю, что вам следует использовать ручку Guice вручную так. Я думаю, вы можете установить фабрику controllerа на экземпляр FXMLLoader, чтобы начать инъекцию. Вот как это делает FXMLView в afterburner.fx . Точная деталь механизма впрыска, используемого в Guice, будет отличаться от механизма afterburner.fx, но я думаю, что широкая концепция установки фабрики controllerа остается аналогичной.

Существует демонстрация фабрики установленных controllerов с использованием FXML и Guice в ответ на: Объединение FXML и Controller в конфигурации модуля Guice .

Жаль, что нет более простого способа сделать это, что не вызывает у вас таких трудностей.

Как несущественная личная сторона примечания, я как бы неоднозначно отношусь к рамкам внедрения инъекций в целом. Конечно, они могут помочь, но много раз для простых вещей я часто бываю в порядке с синглом с методом getInstance, а не с более сложной структурой. Тем не менее, я вижу, как в больших проектах они могут быть полезными, и, конечно же, они очень популярны в некоторых средах Java.

Я изучал эту проблему, и я обнаружил, что инъекция зависимостей вместе с синглом (для модели) – это мой оптимальный дизайн. Я узнал, что использование метода setter для модели в каждом из моих controllerов является формой инъекции зависимостей, поскольку передача модели через конструктор. Spring и Guice – это frameworks, которые помогут этому.

Я попытался использовать Spring, как указано здесь: http://www.zenjava.com/2011/10/23/better-controller-injection/, но я столкнулся с проблемой, когда class конфигурации попытался загрузить controller, он не смог загрузить controllerы элементов. Возможно, это не была проблема с весной, но я подумал, что мне все равно, чтобы потратить время, чтобы заставить ее работать. Кроме того, мне пришлось бы проходить через все мои файлы controllerов и редактировать то, как они были созданы.

Просматривая и много читаю, я обнаружил, что эта статья лучше всего отражает то, что я хотел бы сделать: https://forums.oracle.com/thread/2301217?tstart=0 . Поскольку статья ссылается на предлагаемые улучшения, эти улучшения еще не существуют в JavaFX. Но когда они это сделают, я буду их реализовывать. Для примера, имея возможность вводить модель через fxml:

  

В DataFX Framework появился новый API, называемый DataFX-Flow. С помощью этого API вы можете просто вводить объекты в controller вида. Другое, что здесь поддерживаются области Afterburner.fx. Здесь вы можете найти пример: http://www.guigarage.com/2013/12/datafx-controller-framework-preview/