Два подхода здесь.
Передача модели к вложенным контроллерам
Вы можете вводить контроллер от включенного 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();
Используйте подход MVC: разделить модель между двумя контроллерами и сделать данные доступными из модели. См. Http://stackoverflow.com/questions/32342864/applying-mvc-with-javafx –
Спасибо за подробные инструкции и полный исходный код –
James_D Немного жадный, но у меня есть еще один вопрос для темы расширенных обновлений данных. tableview из другого FXML. Переходя к вашей помощи: D –