所以我已经花了好几个小时来解决这个问题,之前已经在这些论坛上得到了回答,但我真的很感激一些帮助,因为没有人能真正解决我的问题,或提出非常不同的解决方案而且我是不太清楚要尝试什么(即使我已经尝试了所有这些,我敢说)。
问题是:我有一个带有6个场景的JavaFX应用程序及其各自的控制器。我有一个Person类,它创建一个对象,我希望将该对象存储在一个全局的ArrayList中(即所有场景都可以访问),这样当我关闭应用程序时,我可以调用另一个方法来保存它到一个序列化的文件。
我实际上并没有在前几个场景中使用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);
}
我感谢任何帮助:)
答案 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,因为所有屏幕都引用了它