JavaFX – ¿Cómo usar un método en un controlador desde otro controlador?

Trabajando con SceneBuilder. Tengo 2 etapas, cada una con un controlador: stage1Controller, stage2Controller.
Stage1Controller:

public class Stage1Controller { @FXML private MenuItem translate; @FXML private Menu file; @FXML private Menu edit; @FXML private Menu help; @FXML private void handleTranslate (ActionEvent event){ translateFirstStage(); //HOW TO ACCESS THE stage2Controller setLabel()?? } private void translateFirstStage(){ file.setText("Fichier"); edit.setText("Modifier"); help.setText("Aide"); } } 

Stage2Controller:

 public class Stage2Controller { @FXML private Label lb; private void setLabel(String string){ lb.setText("string"); } } 

Aquí se muestra cómo se cargan ambos archivos fxml en la clase Main.java usando 2 métodos (llamados en el método Start (Stage primaryStage)):

 public void firstStage() { try { // Load root layout from fxml file. FXMLLoader loader = new FXMLLoader(); loader.setLocation(Main.class.getResource("view/stage1.fxml")); rootLayout = (BorderPane) loader.load(); // Show the scene containing the root layout. Scene scene = new Scene(rootLayout); primaryStage.setScene(scene); primaryStage.show(); } catch (IOException e) { e.printStackTrace(); } } public void secondStage() { try { // Load root layout from fxml file. FXMLLoader loader = new FXMLLoader(); loader.setLocation(Main.class.getResource("view/stage2.fxml")); XD = (AnchorPane) loader.load(); // Show the scene containing the root layout. Scene scene = new Scene(XD); Stage stage = new Stage(); stage.setScene(scene); stage.show(); } catch (IOException e) { e.printStackTrace(); } } 
  • El método handleTranslate (evento ActionEvent) se usa como método OnAction para la traducción de MenuItem en la primera etapa, traduce la vista en ambas etapas.

¿Cómo puedo poner setLabel en el método handleTranslate? Gracias

La manera “rápida y sucia” es dar al Stage1Controller una referencia al Stage2Controller :

 public class Stage1Controller { private final Stage2Controller stage2Controller ; public void setStage2Controller(Stage2Controller stage2Controller) { this.stage2Controller = stage2Controller ; } // ... @FXML private void handleTranslate (ActionEvent event){ translateFirstStage(); stage2Controller.setLabel(...); } // other code as before ... } 

Ahora en tu aplicación principal:

 public class MainApp extends Application { private Stage1Controller stage1Controller ; private Stage2Controller stage2Controller ; @Override public void start(Stage primaryStage) { firstStage(); secondStage(); stage1Controller.setStage2Controller(stage2Controller); // ... } public void firstStage() { try { // Load root layout from fxml file. FXMLLoader loader = new FXMLLoader(); loader.setLocation(Main.class.getResource("view/stage1.fxml")); rootLayout = (BorderPane) loader.load(); stage1Controller = loader.getController(); // Show the scene containing the root layout. Scene scene = new Scene(rootLayout); primaryStage.setScene(scene); primaryStage.show(); } catch (IOException e) { e.printStackTrace(); } } public void secondStage() { try { // Load root layout from fxml file. FXMLLoader loader = new FXMLLoader(); loader.setLocation(Main.class.getResource("view/stage2.fxml")); XD = (AnchorPane) loader.load(); stage2Controller = loader.getController(); // Show the scene containing the root layout. Scene scene = new Scene(XD); Stage stage = new Stage(); stage.setScene(scene); stage.show(); } catch (IOException e) { e.printStackTrace(); } } // ... } 

Sin embargo, un enfoque más sólido para esto es permitir que ambos controladores accedan a una clase de modelo compartido, almacenando los datos. Si representa los datos utilizando las propiedades observables de JavaFX, los controladores pueden escuchar los cambios en las propiedades que les interesan. Por ejemplo:

 public class Model { private final StringProperty text = new SimpleStringProperty("Initial text..."); public StringProperty textProperty() { return text ; } public final void setText(String text) { textProperty().set(text); } public final String getText() { return textProperty().get(); } // other properties as needed... } 

Ahora sus controladores se verán así:

 public class Stage1Controller { private Model model ; public void setModel(Model model) { this.model = model ; } @FXML private void handleTranslate (ActionEvent event){ translateFirstStage(); model.setText(...); // value will appear in stage2 controller's label! } // ... } 

y

 public class Stage2Controller { @FXML private Label lb ; private Model model ; public void setModel(Model model) { lb.textProperty().unbind(); this.model = model ; lb.textProperty().bind(model.textProperty()); } // ... } 

Y en este caso su aplicación principal se ve así:

 public class MainApp extends Application { private final Model = new Model(); @Override public void start(Stage primaryStage) { // ... } public void firstStage() { try { // Load root layout from fxml file. FXMLLoader loader = new FXMLLoader(); loader.setLocation(Main.class.getResource("view/stage1.fxml")); rootLayout = (BorderPane) loader.load(); Stage1Controller controller = loader.getController(); controller.setModel(model); // Show the scene containing the root layout. Scene scene = new Scene(rootLayout); primaryStage.setScene(scene); primaryStage.show(); } catch (IOException e) { e.printStackTrace(); } } public void secondStage() { try { // Load root layout from fxml file. FXMLLoader loader = new FXMLLoader(); loader.setLocation(Main.class.getResource("view/stage2.fxml")); XD = (AnchorPane) loader.load(); Stage2Controller controller = loader.getController(); controller.setModel(model); // Show the scene containing the root layout. Scene scene = new Scene(XD); Stage stage = new Stage(); stage.setScene(scene); stage.show(); } catch (IOException e) { e.printStackTrace(); } } }