2016-10-27 3 views
0

ссылочных статей Applying MVC With JavaFxJavaFX Обновления TableView от другого FXML

У меня есть интерфейс 1 FXML следующего

<SplitPane> 
    <items> 
     <TableView prefHeight="200.0" prefWidth="200.0"> 
      <columns> 
       <TableColumn prefWidth="75.0" text="User" /> 
       <TableColumn prefWidth="75.0" text="Pass" /> 
      </columns> 
     </TableView> 
     <fx:include source="Container.fxml"/> 
    </items> 
</SplitPane> 

Container.fxml он используется только для примера магазина XML-интерфейса ввод используется для встраивания InputData.fxml , Test.fxml на TabPanel

И интерфейс 3 InputData.xml Я содержит textField имя пользователя и пароль и кнопку сохранения.

Я хотел бы задать каждый раз, когда я нажимаю кнопку сохранить значение, интерфейс 1 таблица может получить и обновление от стоимости интерфейса 3

Поскольку Входной интерфейс-не data.xml встроен непосредственно в интерфейс 1 появляется только когда eligible.So я не могу передавать данные FXML непосредственно к следующему

 DataModel model = new DataModel(); 
     listController.initModel(model); 
     editorController.initModel(model); 
     menuController.initModel(model); 

это на интерфейсе, если можно, пожалуйста, помогите мне

+1

Используйте подход MVC: разделить модель между двумя контроллерами и сделать данные доступными из модели. См. Http://stackoverflow.com/questions/32342864/applying-mvc-with-javafx –

+0

Спасибо за подробные инструкции и полный исходный код –

+0

James_D Немного жадный, но у меня есть еще один вопрос для темы расширенных обновлений данных. tableview из другого FXML. Переходя к вашей помощи: D –

ответ

2

Два подхода здесь.

Передача модели к вложенным контроллерам

Вы можете вводить контроллер от включенного FXML в контроллер для включая FXML используя nested controllers техники. Затем «внешний контроллер» может распространять модель на «вложенный контроллер».

Так, например, если у вас есть

<SplitPane xmlns="..." fx:controller="com.mycompany.MainController"> 
    <items> 
     <TableView prefHeight="200.0" prefWidth="200.0"> 
      <columns> 
       <TableColumn prefWidth="75.0" text="User" /> 
       <TableColumn prefWidth="75.0" text="Pass" /> 
      </columns> 
     </TableView> 
     <fx:include fx:id="container" source="Container.fxml"/> 
    </items> 
</SplitPane> 

Пусть класс контроллера для Container.fxml является ContainerController. Тогда вы могли бы сделать:

public class MainController { 

    private Model model ; 

    @FXML 
    private ContainerController containerController ; // name is fx:id with "Controller" appended 

    public void setModel(Model model) { 
     this.model = model ; 
     containerController.setModel(model); 
     // ... 
    } 

    // ... 
} 

и конечно

public class ContainerController { 

    private Model model ; 

    public void setModel(Model model) { 
     this.model = model ; 
     // ... 
    } 

    // ... 
} 

Использование контроллера завода

Если у вас есть много включенных FXML файлов и контроллеров, и т.д., это может начать, чтобы получить неосновательный , В этом случае лучшим вариантом может быть инициализация модели в конструкторах контроллеров и использование controllerFactory на FXMLLoader для создания контроллеров с моделью, переданной конструктору. Так что теперь вы контроллеры выглядеть следующим образом:

public class MainController { 

    private final Model model ; 

    public MainController(Model model) { 
     this.model = model ; 
    } 

    public void initialize() { 
     // bind controls to model here... 
    } 
} 

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

Теперь вам нужно немного магии для FMXLLoader, чтобы правильно создать контроллеры, когда FXML загружен:

Model model = new Model(); 
FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml")); 
Callback<Class<?>, Object> controllerFactory = (Class<?> type) -> { 
    try { 
     for (Constructor<?> c : type.getConstructors()) { 
      if (c.getParameterCount() == 1 && c.getParameterTypes()[0].equals(Model.class)) { 
       return c.newInstance(model); 
      } 
     } 
     // couldn't find constructor taking a model, just use default: 
     return type.newInstance(); 
    } catch (Exception exc) { 
     exc.printStackTrace(); 
     return null ; 
    } 
}; 
loader.setControllerFactory(controllerFactory); 

Parent root = loader.load(); 
// ... 

Обратите внимание, что FXML файлы, загруженные с помощью <fx:include> тега будет использовать тот же контроллер завод, как " включая «файл FXML. Таким образом, это автоматически передаст ту же модель вложенный контроллер.

Использование DI каркасы

Наконец, если вы действительно многое из этого, вы можете рассмотреть возможность использования рамки INJECT зависимости для управления зависимостями на модели для вас. Afterburner.fx является выделенной рамкой JavaFX DI, а затем все так просто, как

public class MainController { 

    @Inject 
    private Model model ; 

    public void initialize() { 
     // bind UI elements to model... 
    } 
} 

Вы также можете использовать Spring или Guice. Например. с Spring, настройте контроллеры как прототипы beans, модель как одноэлементный компонент и напишите контроллеры для ввода модели, как с afterburner.fx. Тогда вы можете сказать об FXMLLoader использовать Spring для создания контроллеров с

// Spring application context: 
ApplicationContext appContext = ... ; 
FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml")); 
loader.setControllerFactory(appContext::getBean); 
Parent root = loader.load(); 
+0

Метод 1: Таким образом, чтобы передавать значения между интерфейсом 1 Main.fxml и интерфейсом 3 InputData.fxml.I нужно передавать общие значения. Модель для Container.fxml Например, если У меня много контейнеров xml interface: container.fxml содержит container2.fxml содержит InputData. Мне нужно перенести модели из Main.fxml = model-> container.fxml = model-> container2.fxml = model-> InputData.fxml Метод 2: я не понимаю –

+1

@ MaTâm Я не уверен, что я действительно поймите вопрос в своем последнем комментарии: вы точно описали, как он должен работать. Каждый контроллер, которому требуется ссылка на модель, имеет метод setModel. Если у него есть вложенный контроллер, который также нуждается в доступе к модели, его метод setModel вызывает метод setModel вложенного контроллера. Вы можете вложить это настолько глубоко, насколько вам нужно, но, как я уже сказал, это может усложниться, и в этот момент фабрика контроллера может быть проще. –

+0

Hi James_D Спасибо за подробные инструкции, я понял метод 1, это станет проблемой, если слишком много вложенного интерфейса. Ваш метод 2 очень удобен, но я не знаю, как его выполнять. Я могу создавать темы о методе 2, призывать вы продолжаете помогать http://stackoverflow.com/questions/40329861/javafx-using-a-controller-through-factory-to-update-other-xml-interface –

Смежные вопросы