2012-08-28 18 views
25

Goodevening todos,FXML múltiple con controladores, compartir objetos

he encontrado un montón de puestos ya sobre este tema, pero todavía no puede llegar a pasar un objeto de Controller1 a Controller2. ¿Hay algún lugar en un tutorial completo o algún proyecto de ejemplo que haga esto?

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

clase 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 programa, el FXML principal se carga (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 de 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 de capturar el objeto País cuando el Sub1.fxml se carga , lo que significa que tendrá que obtener el objeto 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)!

Lo siento por el largo post, he tratado de ser lo más completa posible otra cosa Nunca entenderé ...

Respuesta

41

FXML es una forma simple de MVC pattern. 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 posible enfoque para introducir el modelo es "contexto". Vamos a considerar un caso, entonces sólo tiene un modelo para todo el proyecto para que pueda tener un contexto global en una 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á 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 al SubController1 y luego cargarlo es xml. Funcionará mejor si no desea tener un modelo global de aplicación.Por lo tanto crear clases similares Contexto 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() 
    } 
} 

contexto Puesta 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); 
} 
+0

Gracias a un millón de veces Sergey, finalmente todo tiene sentido. Esta es la primera vez que tengo que crear una gran aplicación, pero todavía estoy luchando sobre cómo 'compilarla'. También tengo otra pregunta de seguridad que me gustaría preguntar, pero no estoy seguro de si este es el sitio correcto para preguntar (no está relacionado con el código) – Perneel

+0

Hola, Sergey, disculpe el tema anterior. Esto sigue funcionando como un amuleto, pero lo que sí me pregunto ... ¿Hay alguna manera de maximizar el ancho y la altura desde el objeto Node '(Node) fxmlloader.load (url.openStream())' por lo que está vinculado a la ¿ancho y alto del panel (pContenido)? – Perneel

+0

debería funcionar automáticamente, si no, mejor proporcione su código en una pregunta separada –

Cuestiones relacionadas