Javafx 2 将对象从一个场景传递到另一个场景

Javafx 2 将对象从一个场景传递到另一个场景,javafx-2,scene,fxml,Javafx 2,Scene,Fxml,在学习JavaFX2的新世界时,我偶然发现了另一个恼人的问题。我正在开发一个包含多个场景(约10个场景)的程序。为此,我创建了一个小类,如下所示: public class SceneSelector { ... public void setScene(Stage stage, String fxmlfilename, ObservableList ol) throws Exception{ String s = "../" + fxmlfilename;

在学习JavaFX2的新世界时,我偶然发现了另一个恼人的问题。我正在开发一个包含多个场景(约10个场景)的程序。为此,我创建了一个小类,如下所示:

public class SceneSelector {
    ...
    public void setScene(Stage stage, String fxmlfilename, ObservableList ol) throws Exception{
        String s = "../" + fxmlfilename;
        Parent root = FXMLLoader.load(getClass().getResource(s));
        root.setUserData(ol);

        Scene scene = new Scene(root);
        stage.setScene(scene);

        //show the stage
        stage.show();
    }
}
这个类可以很好地在场景之间切换。 现在的问题是,我有时需要将数据从场景1传递到场景2。我试图通过为新场景设置
setUserData()
来实现这一点,除了一件事,新场景基本上可以正常工作。初始化新场景时,如何获取用户数据?(因为此时节点仍然为空)

场景1的代码:

//Code connected to a button that opens the new Scene
private void openLabID(ActionEvent event) throws Exception {       
    final Stage primaryStage = (Stage) btnNewScene.getScene().getWindow();

    ObservableList<Koe> olAfTeWerkenKoeien = DA_Koe.getAfTeWerkenKoeien();
    ss.setScene(primaryStage, "GUI/scenes/koe/Koe.fxml", olAfTeWerkenKoeien);
}
//连接到打开新场景的按钮的代码
私有void openLabID(ActionEvent事件)引发异常{
最终阶段primaryStage=(阶段)btnNewScene.getScene().getWindow();
ObservableList olaftewerkenkoeen=DA_Koe.getaftewerkenkoeen();
ss.setScene(初级阶段,“GUI/scenes/koe/koe.fxml”,olAfTeWerkenKoeien);
}
场景2中的代码:

public void initialize(URL url, ResourceBundle rb) {
    Scene s = lbl.getScene();
    ObservableList<Koe> olAfTeWerkenKoeien = (ObservableList<Koe>) s.getRoot().getUserData();
    System.out.println(olAfTeWerkenKoeien.size());
} 
public void初始化(URL,ResourceBundle-rb){
场景s=lbl.getScene();
ObservableList olAfTeWerkenKoeien=(ObservableList)s.getRoot().getUserData();
System.out.println(olAfTeWerkenKoeien.size());
} 
当然,场景s在这一点上给出了一个空值(因为lbl在这一点上是空的),所以我想知道,是否有一个方法在初始化后立即被触发

当我将此代码附加到Scene2上的按钮时,它就像一个符咒,但应该自动加载

编辑: 使用setMyData()方法设置数据不是问题,但是检索它是:

public ObservableList<Koe> getMyData() {
   return this.myData;
}
公共可观察列表getMyData(){
返回此.myData;
}
当控制器初始化时,如何获取CustomScene对象?因为执行以下操作将导致NullPointerException(因为btnSluiten尚未初始化):

@覆盖
公共void初始化(URL、ResourceBundle rb){
...
Stage Stage=(Stage)btnSluiten.getScene().getWindow();
CustomScene cs=(CustomScene)stage.getScene();
ObservableList olKoe=cs.getMyData();
System.out.println(olKoe.size());
}

我相信您错过了场景对象中的点。从场景类文档中,我们可以看到:

JavaFX场景类是场景图中所有内容的容器

这意味着场景对象只是一个容器,因此不应该包含任何数据

记住这一点,您可以创建另一个具有字段的静态对象,例如

private static Label lbl;

...

public static Label getLbl()
{
    return MyStaticObject.Lbl;
}

...
并使用它来存储您的lbl(或任何适合您的信息的对象),然后静态地检索它


我这样做是为了从应用程序中设置其他阶段对象的所有者。我希望有帮助。干杯

如果您真的希望场景有意义(即存储特定的用户数据),您可以扩展它:

public class FooScene extends Scene {
   private ObservableList myData;

   public setMyData(ObservableList data) {
       this.myData = data;
       //handle data
   }
}
确保在场景初始化后调用设置代码以自己调用它的最简单方法是:

public class SceneSelector {
    ...
    public void setScene(Stage stage, String fxmlfilename, ObservableList ol) throws Exception{
        String s = "../" + fxmlfilename;
        Parent root = FXMLLoader.load(getClass().getResource(s));

        // first: add root to scene
        FooScene scene = new FooScene(root);
        // second: apply data to scene (or root)
        scene.setMyData(ol);
        stage.setScene(scene);

        //show the stage
        stage.show();
    }
}

您可以将控制器用于场景,并通过控制器传递数据:

String filePath1 =  "../" + fxmlfilename;
URL location1 = YourController1.class.getResource(filePath1);
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(location1);
fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());
Parent root = (Node) fxmlLoader.load(location1.openStream());

YourController1 ctrl1 = (YourController1) fxmlLoader.getController();
ctrl1.setUserData();
然后,您可以将数据分配给控制器:

String filePath1 =  "../" + fxmlfilename;
URL location1 = YourController1.class.getResource(filePath1);
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(location1);
fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());
Parent root = (Node) fxmlLoader.load(location1.openStream());

YourController1 ctrl1 = (YourController1) fxmlLoader.getController();
ctrl1.setUserData();
最后,只需根据需要显示场景:

Scene scene = new Scene(root);
stage.setScene(scene);

//show the stage
stage.show();

在控制器中的initialize()方法中,只需像平常一样从控制器数据对象获取数据。

Hi Bruno,感谢您指出这一点,但是对于创建具有许多不同的(使用Java等价物的)“JInternalFrames”的应用程序,最好的解决方案是什么?我知道可以使用Stage对象,但这给了我们额外的窗口,这不是我想要的视图。最好的解决方法是使用一个场景和多个面板,然后只显示/隐藏它们?似乎是最好的方法,您将只有一个场景,因为我们正在讨论JavaFX2,您可以在面板和另一个面板之间添加一些令人眼花缭乱的漂亮过渡,因为警告静态数据是一种边缘攻击。如果您使用单例方法,它是有效的,但是如果您进入共享空间,您就是在自找麻烦。你可以考虑注射方案或者其他方法来保持它。(同样,单身人士也可以)。我正在处理一个类似的问题,但我的方法(到目前为止)是从资源调用一个initialize方法。e、 场景初始化(somePojo);但我们讨论的是一个对象,它在多个场景中使用。或者是我的情况,几个阶段的唯一所有者。这不就是单身汉应该代表的吗?一个类,一个全局实例?我看不到任何bordeline黑客thereHi Sergey,这确实是个好主意。但是,这仍然会导致相同的问题,即我无法在initialize()方法中从控制器获取场景对象?还是我在这里遗漏了什么?我明白了。我没有从您的问题中看到您正在通过fxml加载场景。等等,我会更新一个答案。嘿,谢尔盖,我完全理解这个概念,它是一种魅力,但我仍然被这样一个事实所困扰:在初始化时无法获得场景对象?请参阅更新的问题PS:setMyData方法有一个输入错误,您在发布后忘记了“void”谢谢。。。你救了我的命:我不知道为什么在另一个控制器上的“initialize”方法中userData会为null?你必须在控制器初始化后设置对象,在初始化过程中,userData对象肯定应该为null。