如何在关闭阶段之前从阶段中获得 return 值?
How to return value from a stage before closing it?
我有一个“主阶段”,我按下按钮打开“第二阶段”,我有一个 table,用户选择 table 中的一项并单击“asignar”按钮(只是一个确认按钮),一旦点击,它必须return在table中选择的项目的代码到主阶段并关闭第二阶段。
这是重要的代码。
我有一个 INT 变量,它必须取一个函数的值:
codigo = controller.setVista(this, usuario, password);
“setVista”函数是这样的:
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;
}
像这样的“asignarSeleccion”:
private void asignarSeleccion() {
final HorarioTableModelo aux_horario = getTablaSeleccionada();
posicion = datos.indexOf(aux_horario);
if (aux_horario != null) {
codigo_horario = aux_horario.getCodigo();
}
}
我的问题是我无法在阶段关闭前将“codigo_horario”值放入第一个变量“codigo”中,我缺少什么?
这是一个可能的例子。结构同in the answer in my comment.
第二个 Stage
通过 "controller" 打开,它存储即使 Stage
关闭也应返回的数据,并公开 getter用于从外部世界检索值。
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;
}
}
}
您可以使用 return 语句编写自己的舞台 class。
public class MyStage extends Stage {
public String showAndReturn(myFXControll controll) {
super.showAndWait();
return controll.getReturn();
}
}
之后你必须为你的控制器定义一个return函数。
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
}
}
现在您可以从父控制器控制您的 return。
String retValue=myStage.showAndReturn(childControll);
System.out.println(retValue);
我认为这是一个干净代码的好解决方案。您还可以使用 Screen Builder 设计 FXML 样式。
在我的主控制器中,我创建了 Stage。我可以像任何 class 一样使用的负载控制器。通过创建一个事件,我可以在关闭 window.
之前获取数据
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?");
}
我的其他 mySceneBuilderWindowController 方法:
public void iCanSendDataToCtrl(String giveMe) {
// do something ex. myTextBox.setText(giveMe);
}
public String iCanGetDataBeforeClose() {
// do something ex. return myTextBox.getText();
}
4baad4 的示例中存在一些错误。如果controller中的方法是iCanGetDataBeforeClose,那么应该这样调用:
String someValue = controller.iCanGetDataBeforeClose();
但即使这样也不适合我。我实际上根本没有使用 setOnCloseRequest 就让它工作了。在表单控制器中,我有一个这样的方法:
public boolean getCompleted() {
return this.finished;
}
然后在表单中调用它:
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("myView.fxml"));
AnchorPane pane = (AnchorPane) loader.load();
myViewController controller = loader.getController();
Scene scene = new Scene(pane);
Stage stage = new Stage();
stage.setScene(scene);
stage.showAndWait();
if (controller.getCompleted()){
doStuff();
}
有人可能会认为,由于阶段已经退出,控制器会抛出空引用异常,但它没有,它返回了正确的响应。
这个解决方案有效,并且是最简单的恕我直言。
我有一个“主阶段”,我按下按钮打开“第二阶段”,我有一个 table,用户选择 table 中的一项并单击“asignar”按钮(只是一个确认按钮),一旦点击,它必须return在table中选择的项目的代码到主阶段并关闭第二阶段。
这是重要的代码。
我有一个 INT 变量,它必须取一个函数的值:
codigo = controller.setVista(this, usuario, password);
“setVista”函数是这样的:
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;
}
像这样的“asignarSeleccion”:
private void asignarSeleccion() {
final HorarioTableModelo aux_horario = getTablaSeleccionada();
posicion = datos.indexOf(aux_horario);
if (aux_horario != null) {
codigo_horario = aux_horario.getCodigo();
}
}
我的问题是我无法在阶段关闭前将“codigo_horario”值放入第一个变量“codigo”中,我缺少什么?
这是一个可能的例子。结构同in the answer in my comment.
第二个 Stage
通过 "controller" 打开,它存储即使 Stage
关闭也应返回的数据,并公开 getter用于从外部世界检索值。
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;
}
}
}
您可以使用 return 语句编写自己的舞台 class。
public class MyStage extends Stage {
public String showAndReturn(myFXControll controll) {
super.showAndWait();
return controll.getReturn();
}
}
之后你必须为你的控制器定义一个return函数。
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
}
}
现在您可以从父控制器控制您的 return。
String retValue=myStage.showAndReturn(childControll);
System.out.println(retValue);
我认为这是一个干净代码的好解决方案。您还可以使用 Screen Builder 设计 FXML 样式。
在我的主控制器中,我创建了 Stage。我可以像任何 class 一样使用的负载控制器。通过创建一个事件,我可以在关闭 window.
之前获取数据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?");
}
我的其他 mySceneBuilderWindowController 方法:
public void iCanSendDataToCtrl(String giveMe) {
// do something ex. myTextBox.setText(giveMe);
}
public String iCanGetDataBeforeClose() {
// do something ex. return myTextBox.getText();
}
4baad4 的示例中存在一些错误。如果controller中的方法是iCanGetDataBeforeClose,那么应该这样调用:
String someValue = controller.iCanGetDataBeforeClose();
但即使这样也不适合我。我实际上根本没有使用 setOnCloseRequest 就让它工作了。在表单控制器中,我有一个这样的方法:
public boolean getCompleted() {
return this.finished;
}
然后在表单中调用它:
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("myView.fxml"));
AnchorPane pane = (AnchorPane) loader.load();
myViewController controller = loader.getController();
Scene scene = new Scene(pane);
Stage stage = new Stage();
stage.setScene(scene);
stage.showAndWait();
if (controller.getCompleted()){
doStuff();
}
有人可能会认为,由于阶段已经退出,控制器会抛出空引用异常,但它没有,它返回了正确的响应。
这个解决方案有效,并且是最简单的恕我直言。