将数据通过Java FX Controller传递到其他View

时间:2016-09-08 17:20:57

标签: java javafx controller fxmlloader

我想这是一个简单的问题,但这是漫长的一天工作,我现在无法想出正确的方法。

我有3个FXML文件。

  • Menge.fxml
  • Start.fxml
  • Suche.fxml

我像往常一样从Main.java开始

@Override
public void start(Stage primaryStage) {
    try {
        AnchorPane root = (AnchorPane)FXMLLoader.load(getClass().getResource("Start.fxml"));
        Scene scene = new Scene(root);
        scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
        primaryStage.setScene(scene);
        primaryStage.show();
    } catch(Exception e) {
        e.printStackTrace();
    }
}

MainController内,我有以下ActionListener

@FXML
void actionListenerMenge(ActionEvent event) {
    try {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Menge.fxml"));
        Parent root1 = (Parent) fxmlLoader.load();
        Stage stage = new Stage();
        stage.setScene(new Scene(root1));  
        stage.show();
    } catch(Exception e) {
        e.printStackTrace();
    }
}

所以我通过FXMLLoader打开Suche.fxml。 现在我的Suche-View中有一个button,它打开另一个场景,用户应该搜索特定的数据记录。

@FXML
void actionListenerSuche(ActionEvent event) {
    try {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Suche.fxml"));
        Parent root1 = (Parent) fxmlLoader.load();
        Stage stage = new Stage();
        stage.setScene(new Scene(root1));  
        stage.show();
    } catch(Exception e) {
        e.printStackTrace();
    }
}

SucheController我通过FXMLLoader再次加载MengeController

FXMLLoader loader = new FXMLLoader(getClass().getResource("Menge.fxml"));
try {
    Parent root = loader.load();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
MengeController controller = (MengeController)loader.getController();

我想修改TextField @ MengeController内的值,以便从我的Menge.fxml更新视图。但是如果我做的话

controller.setTextFieldValue("abc")它没有更新。我知道这一定是因为我已经加载MengeController两次,所以有两个实例。但我不知道如何只加载一次或注入它来更新TextField内的MengeController

1 个答案:

答案 0 :(得分:1)

选项1:观察SucheController

中的属性

SucheController中定义属性。而不是尝试将引用返回到MengeController,只需设置属性:

public class SucheController {

    private final ObjectProperty<Foo> foo = new SimpleObjectProperty<>();

    public ObjectProperty<Foo> fooProperty() {
        return foo() ;
    }

    public final Foo getFoo() {
        return fooProperty().get();
    }

    public final void setFoo(Foo foo) {
        fooProperty().set(foo);
    }

    // ...

    @FXML
    private void someHandlerMethod() {

        // FXMLLoader loader = new FXMLLoader(getClass().getResource("Menge.fxml"));
        // try {
        //     Parent root = loader.load();
        // } catch (IOException e) {
        //     e.printStackTrace();
        // }
        // MengeController controller = (MengeController)loader.getController();

        setFoo(...);
    }
}

显然将Foo替换为表示用户在此处提供的任何数据的类型,并相应地命名属性和方法......

现在加载Suche.fxml时,只需获取对控制器的引用并观察属性。然后,您可以直接在MengeController本身更新文本字段:

@FXML
void actionListenerSuche(ActionEvent event) {
    try {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Suche.fxml"));
        Parent root1 = (Parent) fxmlLoader.load();

        SucheController sucheController = loader.getController();
        sucheController.fooProperty().addListener((obs, oldFoo, newFoo) -> {
            someTextField.setText(newFoo.getSomeValue());
            // ...
        });

        Stage stage = new Stage();
        stage.setScene(new Scene(root1));  
        stage.show();
    } catch(Exception e) {
        e.printStackTrace();
    }
}

选项2:将对MengeController的引用直接传递给SucheController

另一个选项,我不喜欢它涉及控制器之间的更多耦合,只是将对MengeController的引用传递给SucheController

public class SucheController {

    private MengeController mengeController ;

    public void setMengeController(MengeController mengeController) {
        this.mengeController = mengeController ;
    }

    // ...

    @FXML
    private void someHandlerMethod() {

        mengeController.setTextFieldValue("abc");

    }
}

然后加载Suche.fxml的MengeController中的代码看起来像

@FXML
void actionListenerSuche(ActionEvent event) {
    try {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Suche.fxml"));
        Parent root1 = (Parent) fxmlLoader.load();

        SucheController sucheController = fxmlLoader.getController();
        sucheController.setMengeController(this);

        Stage stage = new Stage();
        stage.setScene(new Scene(root1));  
        stage.show();
    } catch(Exception e) {
        e.printStackTrace();
    }
}
相关问题