javafx return-value stage

javafx - ¿Cómo devolver el valor de una etapa antes de cerrarla?



return-value stage (3)

Antes que nada, perdón por el mal inglés.

Aquí está el caso:

Tengo una "etapa principal" donde presiono un botón para abrir una "segunda etapa" donde tengo una tabla, el usuario selecciona un elemento de la tabla y hace clic en el botón "asignar" (que es solo un botón de confirmación), una vez que se hace clic, debe devolver el código del elemento seleccionado en la tabla a la etapa principal y cerrar la segunda etapa.

Aquí está el código que importa.

Tengo una variable INT que debe tomar el valor de una función:

codigo = controller.setVista(this, usuario, password);

La función "setVista" es así:

public int setVista(ListHorarios vista, String usuario, String password) { this.vista = vista; this.usuario = usuario; this.password = password; this.inicializarTabla(); this.actualizarTabla(0, "%"); btnSeleccionar.setOnAction(e -> { asignarSeleccion(); Stage stage = (Stage) btnSeleccionar.getScene().getWindow(); stage.close(); }); return codigo_horario; }

Y la "asignaciónSeleccion" así:

private void asignarSeleccion() { final HorarioTableModelo aux_horario = getTablaSeleccionada(); posicion = datos.indexOf(aux_horario); if (aux_horario != null) { codigo_horario = aux_horario.getCodigo(); } }

Mi problema es que no puedo obtener el valor "codigo_horario" en la primera variable "codigo" antes de que cierre la etapa, ¿qué me falta?


Aquí hay un posible ejemplo. La estructura es la misma que en la respuesta en mi comentario .

La segunda Stage se abre a través de un "controlador" que almacena los datos que deben devolverse incluso cuando la Stage está cerrada y expone un captador que se utilizará para recuperar el valor del mundo exterior.

import javafx.application.Application; import javafx.stage.Modality; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TextField; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; public class Main extends Application { @Override public void start(Stage primaryStage) { try { BorderPane root = new BorderPane(); Scene scene = new Scene(root,400,400); Button bSecondStage = new Button("Show second Stage"); bSecondStage.setOnAction(e -> { WindowController wc = new WindowController(); wc.showStage(); System.out.println(wc.getData()); }); root.setCenter(bSecondStage); primaryStage.setScene(scene); primaryStage.show(); } catch(Exception e) { e.printStackTrace(); } } public static void main(String[] args) { launch(args); } class WindowController { private String data; void showStage() { Stage stage = new Stage(); stage.initModality(Modality.APPLICATION_MODAL); VBox root = new VBox(); Scene scene = new Scene(root); TextField tf = new TextField(); Button submit = new Button("Submit"); submit.setOnAction(e -> { data = tf.getText(); stage.close(); }); root.getChildren().addAll(tf, submit); stage.setScene(scene); stage.showAndWait(); } String getData() { return data; } } }


En mi controlador principal creo Stage. Controlador de carga que puedo usar como cualquier clase. Y al crear un evento puedo obtener datos justo antes de cerrar la ventana.

try { FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("/package/mySceneBuilderWindow.fxml")); final Pane rootPane = (Pane)loader.load(); Scene scene = new Scene(rootPane); Stage stage = new Stage(); stage.setTitle("Optional title"); stage.setScene(scene); mySceneBuilderWindowController controller = loader.<mySceneBuilderWindowController>getController(); controller.iCanSendDataToCtrl("String for now"); // sending data or init textFields... stage.show(); /* set event which is fired on close // How to close in the other window... (pressing X is OK too) @FXML private Button fxidSave = new Button(); // global var @FXML private void handleSaveButton() { Stage stage = (Stage) fxidSave.getScene().getWindow(); stage.close(); // closes window } */ stage.setOnCloseRequest((EventHandler<WindowEvent>) new EventHandler<WindowEvent>() { public void handle(WindowEvent we) { String iCanGetDataBeforeClose = controller.getData(); System.out.println(iCanGetDataBeforeClose); // static class can be used aswell -> System.out.println(Context.getMyString()); } }); } catch (IOException e) { System.out.println("something wrong with .fxml - name wrong? path wrong? building error?"); }

Mis otros métodos mySceneBuilderWindowController:

public void iCanSendDataToCtrl(String giveMe) { // do something ex. myTextBox.setText(giveMe); } public String iCanGetDataBeforeClose() { // do something ex. return myTextBox.getText(); }


Puede escribir su propia clase Stage con una declaración de devolución.

public class MyStage extends Stage { public String showAndReturn(myFXControll controll) { super.showAndWait(); return controll.getReturn(); } }

Después de eso, debe definir una función de retorno a su controlador.

public class TableFilterControll implements Initializable { @Override public void initialize(URL arg0, ResourceBundle arg1) { } public String getReturn() { return "I''m a nice return value"; //return what you want controlled by your controller class } }

Ahora puede controlar su retorno desde el controlador principal.

String retValue=myStage.showAndReturn(childControll); System.out.println(retValue);

Creo que esta es una buena solución para un código limpio. Y puede diseñar su FXML con Screne Builder.