【问题标题】:How to pass an ArrayList from one Scene to another in JavaFX 2?如何在 JavaFX 2 中将 ArrayList 从一个场景传递到另一个场景?
【发布时间】:2014-03-17 06:43:56
【问题描述】:

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

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

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

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

  1. 在哪里声明ArrayList(如果在main方法中,是main Class还是在哪里?)
  2. 如何在场景之间传递此 ArrayList,以便它们都能够访问它们。

我目前使用这个类在场景之间切换:

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

感谢您的帮助:)

【问题讨论】:

    标签: java arraylist javafx javafx-2


    【解决方案1】:

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

    一种方法是在您的代码中创建控制器,使用共享列表初始化它们,然后将它们传递给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);
        }
    }
    

    对于需要访问共享数据的控制器,只需定义一个带有参数的构造函数即可:

    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

    【讨论】:

    • 谢谢,这似乎解决了问题。除了,现在我可以从任何类中读取 ArrayList 但我不能写回它(即更新它)......这样我就可以在一个场景中添加东西,不同的场景将能够看到这些变化......如何我要这样做吗?
    • 只要将相同的列表实例传递给每个控制器,这将起作用。所以要么确保你只实例化 SelectScene 一次;或实例化 List 一次(例如在 start 方法中)并将列表的相同实例传递给 SelectScene 构造函数。如果你需要动态观察变化,你可能需要一个 ObservableList 而不是一个普通的列表。
    • 为了能够使用我的 SelectScene 类中的方法(setScene),我在每个控制器中实例化它......因为我不能静态地做它,它会引发错误......如何(或在哪里)你会只实例化一次就可以在所有场景中使用它吗?
    • 在这种情况下,您可以将 List 定义为 SelectScene 构造函数中的参数,并使用该参数来初始化字段。然后使用 controllerFactory 技术将单个列表实例传递给所有控制器,并将列表传递给 SelectScene 构造函数。这样你就有多个 SelectScenes 但它们都共享同一个列表。我会稍微更新一下代码......关键是你只创建一个列表。如果您在主应用程序的 start(...) 方法中创建列表,并且没有其他地方,您可以保证这一点。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多