Múltiples FXML con controladores, compartir objeto

Buenas tardes a todos,

Ya encontré un montón de publicaciones sobre este tema, pero aún no logro pasar un objeto de Controller1 a Controller2. ¿Hay algún lugar en un tutorial completo o algún proyecto de ejemplo que haga esto?

He llegado hasta aquí hasta que me quedé atrapado:

Clase de país

public class Country { private SimpleStringProperty country = new SimpleStringProperty(""); //Constructor public Country() { } //GETTERS public String getCountry() { return country.get(); } //SETTERS public void setCountry(String value) { country.set(value); } @Override public String toString() { return getCountry(); } } 

Cuando se inicia el progtwig, se carga el FXML principal (Sample.fxml). Esto contiene un panel de borde con una barra de menú en el panel superior y un panel de contenido en el centro. Al inicializar, creo un nuevo objeto Country y lo almaceno en una variable global. Tengo un método que carga otro FXML en el panel de contenido cuando se hace clic en un elemento del menú:

SampleController.java

 public class SampleController implements Initializable { @FXML private Pane pContent; private Country c; @FXML private void handleButtonAction(ActionEvent event) throws IOException { System.out.println(c); //this prints Belgium, which is correct URL url = getClass().getResource("Sub1.fxml"); FXMLLoader fxmlloader = new FXMLLoader(); fxmlloader.setLocation(url); fxmlloader.setBuilderFactory(new JavaFXBuilderFactory()); pContent.getChildren().clear(); pContent.getChildren().add((Node) fxmlloader.load(url.openStream())); } @Override public void initialize(URL url, ResourceBundle rb) { c = new Country(); c.setCountry("Belgium"); } public Country getCountryFromSampleController(){ return c; } } 

Ahora deseo capturar el objeto Country cuando se carga el Sub1.fxml, lo que significa que necesito recuperar el objeto del país en initialize ():

Sub1Controller.java

 public class Sub1Controller implements Initializable { /** * Initializes the controller class. */ @Override public void initialize(URL url, ResourceBundle rb) { SampleController sp = new SampleController(); //I don't know how to fetch the original SampleController object System.out.println(sp.getCountryFromSampleController()); //this prints null, which is ofcourse logical because I make a new SampleController object. } } 

La pregunta que tengo, ¿cómo puedo obtener el objeto SampleController ‘original’ para que pueda usar el método getCountryFromRoot () para obtener el objeto Country con valor Belgium? He estado buscando este tema durante horas y he leído todas las publicaciones de StackOverflow sobre esto, pero parece que no encuentro el enlace que falta … ¡se agradece cualquier ayuda (preferiblemente con este código)!

Perdón por la publicación larga, traté de ser lo más completa posible, nunca lo entenderé …

FXML es una forma simple de patrón MVC . El archivo FXML es una vista, el controlador es obvio, ¿qué se ha perdido? El modelo: un lugar donde almacena todos los datos relativos a su vista actual y, por lo tanto, que puede usar para compartir datos de país entre los controladores.


1. Uno de los posibles enfoques para introducir el modelo es el “contexto”. Consideremos un caso, entonces solo tiene un modelo para todo el proyecto para que pueda tener un contexto global en forma de Singleton

 public class Context { private final static Context instance = new Context(); public static Context getInstance() { return instance; } private Country country = new Country(); public Country currentCountry() { return country; } } 

Su SampleController tendrá los siguientes cambios:

 @Override public void initialize(URL url, ResourceBundle rb) { Context.getInstance().currentCountry().setCountry("Belgium"); } 

Y SubController1 puede acceder a él de la misma manera:

 @Override public void initialize(URL url, ResourceBundle rb) { System.out.println(Context.getInstance().currentCountry().getCountry()); } 

2. Otra forma es pasar el contexto a SubController1 luego cargarlo es xml. Funcionará mejor si no desea tener un modelo global de aplicación. Por lo tanto, cree una clase de contexto similar pero sin campos de instancia, y:

 public class Sub1Controller implements Initializable { private Context context; public void setContext(Context context) { this.context = context; // initialize country dependent data here rather then in initialize() } } 

Configuración del contexto en SampleController :

 Context currentContext = new Context(); @Override public void initialize(URL url, ResourceBundle rb) { currentContext.currentCountry().setCountry("Belgium"); } @FXML private void handleButtonAction(ActionEvent event) throws IOException { URL url = getClass().getResource("Sub1.fxml"); FXMLLoader fxmlloader = new FXMLLoader(); fxmlloader.setLocation(url); fxmlloader.setBuilderFactory(new JavaFXBuilderFactory()); pContent.getChildren().clear(); pContent.getChildren().add((Node) fxmlloader.load(url.openStream())); // here we go ((Sub1Controller)fxmlloader.getController()).setContext(currentContext); } 

mediante el uso de Flow API de DataFX puede inyectar datos en las instancias de su controlador mediante el uso de CDI: