在JavaFX2中,如何将ArrayList从一个场景传递到另一个场景?
因此,我已经尝试了几个小时来解决这个问题,之前在这些论坛上已经得到了回答,但我真的非常感谢一些帮助,因为没有人真正解决我的问题或提出非常不同的解决方案,我也不太确定该尝试什么(尽管我敢说,我已经尝试了所有这些) 问题是:我有一个JavaFX应用程序,它有6个场景和它们各自的控制器。我有一个Person类,它创建了一个对象,我想将该对象存储在全局的ArrayList中(也就是说,所有场景都可以访问),这样当我关闭应用程序时,我可以调用另一个方法将其保存到序列化文件中 在前两个场景中,我实际上没有使用ArrayList,因为它们是菜单,所以创建对象的实际方法直到第三个场景左右才运行 我已经成功地创建了场景,我可以在它们之间切换,我只是不知道在JavaFX2中,如何将ArrayList从一个场景传递到另一个场景?,java,arraylist,javafx,javafx-2,Java,Arraylist,Javafx,Javafx 2,因此,我已经尝试了几个小时来解决这个问题,之前在这些论坛上已经得到了回答,但我真的非常感谢一些帮助,因为没有人真正解决我的问题或提出非常不同的解决方案,我也不太确定该尝试什么(尽管我敢说,我已经尝试了所有这些) 问题是:我有一个JavaFX应用程序,它有6个场景和它们各自的控制器。我有一个Person类,它创建了一个对象,我想将该对象存储在全局的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);
}
非常感谢您的帮助:)我建议您查看我的系统架构。在我的示例中,您可以将arraylist存储在MyScreenController类中,因为所有屏幕都有对它的引用,有几种方法可以做到这一点:基本上,所有这些方法都不使用静态的
FXMLLoader.load(URL)
方法,而是创建一个FXMLLoader
实例
一种方法是在代码中创建控制器,用共享列表初始化它们,然后将它们传递给setController(…)
。在此版本中,您将从FXML文件中删除fx:controller
属性
不过,在您的情况下,似乎更好的方法是为fxmloader
定义一个控制器工厂。这是一个告诉fxmloader
如何从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类选择场景{
私有回调,对象>(){
@凌驾
公共对象调用(类类型){
试一试{
构造函数=type.getDeclaredConstructor(List.class);
返回构造函数.newInstance(数据);
}捕获(NoSuchMethodException){
返回类型:newInstance();
}捕获(例外情况除外){
//麻烦。。。
例如printStackTrace();
返回null;
}
}
};
}
public void setScene(字符串fxmlFileName、字符串标题、ActionEvent事件)引发IOException{
Stage Stage=(Stage)((节点)event.getSource()).getScene().getWindow();
FXMLLoader=新的FXMLLoader(getClass().getResource(fxmlFileName));
loader.setControllerFactory(controllerFactory);
父根=(父)加载程序。加载();
场景=新场景(根);
scene.getStylesheets().add(FinalDossier.class.getResource(“style.css”).toExternalForm());
舞台。片名(片名);
舞台场景;
}
}
对于需要访问共享数据的控制器,只需定义一个构造函数,其中的参数包含一个列表:
public class MyController {
private final List<...> data ;
public MyController(List<...> data) {
this.data = data ;
}
public void initialize() {
// usual initialize method
}
}
公共类MyController{
私人最终名单数据;
公共MyController(列表数据){
这个数据=数据;
}
公共无效初始化(){
//常用初始化方法
}
}
对于没有该构造函数的控制器,控制器工厂将返回默认构造函数
您可以在任何方便的地方定义该列表:直接在SelectScene类中(如代码所示),或者可以在前面定义它(例如,在start()方法中),并将其传递给SelectScene构造函数。这取决于你可能需要访问它的其他地方
更新:完整示例谢谢,这似乎解决了问题。除此之外,现在我可以从任何类读取ArrayList,但我不能回写它(即更新它)。。。所以我可以在一个场景中添加内容,不同的场景可以看到这些变化。。。我该怎么做呢?只要将列表的同一个实例传递给每个控制器,就可以了。因此,要么确保只实例化一次SelectScene;或者实例化列表一次(比如在start方法中),并将相同的列表实例传递给SelectScene构造函数。如果需要动态观察更改,可能需要一个ObservableList而不是普通列表。为了能够使用SelectScene类中的方法(setScene),我在每个控制器中实例化它。。。因为我不能静态地做它,它会抛出一个错误。。。如何(或在何处)仅实例化一次,并且能够在所有场景中使用它?在这种情况下,您可以在SelectScene构造函数中将列表定义为参数,并使用该参数初始化字段。然后使用controllerFactory技术将单个列表实例传递给所有控制器,并将列表传递给SelectScene构造函数。这样,您就有了多个SelectScenes,但它们都共享同一个列表。我会更新一下代码。。。关键的是,您只创建一个列表。如果您在主应用程序的start(…)方法中创建列表,而不是在其他任何地方,则可以保证这一点