【问题标题】:How to return value from a stage before closing it?如何在关闭阶段之前从阶段返回值?
【发布时间】:2016-11-18 12:01:54
【问题描述】:

我有一个“主阶段”,我按下一个按钮打开一个“第二阶段”,我有一个表格,用户选择表格的一个项目并点击“asignar”按钮(这只是一个确认按钮),一旦点击,必须将表中选中项的代码返回到主阶段并关闭第二阶段。

这是重要的代码。

我有一个 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”,我缺少什么?

【问题讨论】:

  • @DVarga 在那篇文章中,他们将数据从第一个传递到第二个,我想以相反的方式进行
  • 我开始使用 sqlite 或内置属性类在控制器之间传递数据。

标签: javafx return-value stage


【解决方案1】:

这是一个可能的例子。结构与in the answer in my comment相同。

第二个Stage 是通过一个“控制器”打开的,该控制器存储即使在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;
        }
    }
}

【讨论】:

  • 这个例子真的帮助我解决了我的问题!谢谢!
【解决方案2】:

您可以使用 return 语句编写自己的 Stage 类。

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

之后你必须为你的控制器定义一个返回函数。

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
    }
}

现在您可以控制从父控制器返回。

String retValue=myStage.showAndReturn(childControll);

System.out.println(retValue);

我认为这是干净代码的一个很好的解决方案。您可以使用 Screen Builder 设置 FXML 样式。

【讨论】:

    【解决方案3】:

    4baad4 的示例中有一些错误。如果控制器中的方法是 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();
    }
    

    有人可能会认为,由于阶段已经退出,控制器会抛出空引用异常,但事实并非如此,它返回了正确的响应。

    此解决方案有效,并且是最简单的恕我直言。

    【讨论】:

      【解决方案4】:

      在我的主控制器中,我创建了 Stage。我可以像任何类一样使用的加载控制器。通过创建一个事件,我可以在关闭窗口之前获取数据。

      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();
       }
      

      【讨论】:

        猜你喜欢
        • 2014-08-20
        • 2012-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多