如何在JavaFX 2中将ArrayList从一个场景传递到另一个场景?

时间:2014-03-17 06:43:57

标签: java arraylist javafx javafx-2

所以我已经花了好几个小时来解决这个问题,之前已经在这些论坛上得到了回答,但我真的很感激一些帮助,因为没有人能真正解决我的问题,或提出非常不同的解决方案而且我是不太清楚要尝试什么(即使我已经尝试了所有这些,我敢说)。

问题是:我有一个带有6个场景的JavaFX应用程序及其各自的控制器。我有一个Person类,它创建一个对象,我希望将该对象存储在一个全局的ArrayList中(即所有场景都可以访问),这样当我关闭应用程序时,我可以调用另一个方法来保存它到一个序列化的文件。

我实际上并没有在前几个场景中使用ArrayList,因为它们是菜单,所以创建对象的实际方法直到第三个场景才会运行。

我已经成功创建了场景,我可以在它们之间切换,我只是不知道

  1. 在哪里声明ArrayList(如果在main方法中,主类或在哪里?)
  2. 如何在场景之间传递此ArrayList,以便他们都可以访问它们。
  3. 我目前使用此类在场景之间切换:

    public class SelectScene  {
        public void setScene(String fxmlFileName, String title, ActionEvent event) throws IOException{
            Stage stage = (Stage) ((Node)event.getSource()).getScene().getWindow();
            Parent root = FXMLLoader.load(getClass().getResource(fxmlFileName));
            Scene scene = new Scene(root);
            scene.getStylesheets().add(FinalDossier.class.getResource("style.css").toExternalForm());
            stage.setTitle(title);
            stage.setScene(scene);
        }
    

    我感谢任何帮助:)

2 个答案:

答案 0 :(得分:2)

有几种方法可以做到这一点:基本上所有这些方法都涉及不使用静态FXMLLoader.load(URL)方法,而是创建FXMLLoader实例。

一种方法是在代码中创建控制器,使用共享List初始化它们,然后将它们传递给setController(...)。在此版本中,您将从FXML文件中删除fx:controller属性。

在您的情况下,似乎更好的方法是为FXMLLoader定义控制器工厂。这是一个告诉FXMLLoader如何从fx:controller属性中定义的类名获取实例的对象。这只涉及一点点反射魔法。所以你会做类似

的事情
public class SelectScene  {


    private Callback<Class<?>, Object> controllerFactory ;

    public SelectScene(final List<...> data) {
        controllerFactory = new Callback<Class<?>, Object>() {
            @Override
            public Object call(Class<?> type) {
                try {
                    Constructor<?> constructor = type.getDeclaredConstructor(List.class);
                    return constructor.newInstance(data);
                } catch (NoSuchMethodException exc) {
                    return type.newInstance();
                } catch (Exception ex) {
                    // trouble...
                    ex.printStackTrace();
                    return null ;
                }
            }
         };
    }

    public void setScene(String fxmlFileName, String title, ActionEvent event) throws IOException{
        Stage stage = (Stage) ((Node)event.getSource()).getScene().getWindow();
        FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlFileName));
        loader.setControllerFactory(controllerFactory);
        Parent root = (Parent)loader.load();
        Scene scene = new Scene(root);
        scene.getStylesheets().add(FinalDossier.class.getResource("style.css").toExternalForm());
        stage.setTitle(title);
        stage.setScene(scene);
    }
}

对于需要访问共享数据的控制器,只需使用带List的参数定义构造函数:

public class MyController {
    private final List<...> data ;
    public MyController(List<...> data) {
        this.data = data ;
    }
    public void initialize() {
        // usual initialize method
    }
}

对于没有该构造函数的控制器,控制器工厂将回退到默认构造函数。

您可以在任何方便的位置定义List:直接在SelectScene类中(如代码所示),或者您可以更早地定义它(例如在start()方法中),并传递它进入SelectScene构造函数。它只取决于您可能需要访问它的其他位置。

更新:完整示例here

答案 1 :(得分:0)

我建议查看javafx-MultipleScreens-framework的架构。在我的示例中,您可以在MyScreenController类中存储arraylist,因为所有屏幕都引用了它