大家晚上好,
我已经找到了很多关于这个主题的帖子,但我仍然无法将对象从 Controller1 传递到 Controller2。是否有完整的教程或一些示例项目可以做到这一点?
我已经走了这么远,直到我被卡住了:
乡村类
public class Country {
private SimpleStringProperty country = new SimpleStringProperty("");
//Constructor
public Country() {
}
//GETTERS
public String getCountry() {
return country.get();
}
//SETTERS
public void setCountry(String value) {
country.set(value);
}
@Override
public String toString() {
return getCountry();
}
}
当程序启动时,主 FXML 被加载 (Sample.fxml)。它包含一个边框 Pane ,顶部面板中有一个菜单栏,中间有一个内容 Pane 。在初始化时,我创建了一个新的 Country 对象并将其存储在一个全局变量中。我有一种方法可以在单击菜单项时将另一个 FXML 加载到内容 Pane 中:
示例 Controller .java
public class SampleController implements Initializable {
@FXML
private Pane pContent;
private Country c;
@FXML
private void handleButtonAction(ActionEvent event) throws IOException {
System.out.println(c); //this prints Belgium, which is correct
URL url = getClass().getResource("Sub1.fxml");
FXMLLoader fxmlloader = new FXMLLoader();
fxmlloader.setLocation(url);
fxmlloader.setBuilderFactory(new JavaFXBuilderFactory());
pContent.getChildren().clear();
pContent.getChildren().add((Node) fxmlloader.load(url.openStream()));
}
@Override
public void initialize(URL url, ResourceBundle rb) {
c = new Country();
c.setCountry("Belgium");
}
public Country getCountryFromSampleController(){
return c;
}
}
现在我希望在加载 Sub1.fxml 时捕获 Country 对象,这意味着我需要在 initialize() 上获取 country 对象:
子 Controller .java
public class Sub1Controller implements Initializable {
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
SampleController sp = new SampleController(); //I don't know how to fetch the original SampleController object
System.out.println(sp.getCountryFromSampleController());
//this prints null, which is ofcourse logical because I make a new SampleController object.
}
}
我的问题是,如何获取“原始” SampleController 对象,以便我可以使用 getCountryFromRoot() 方法来获取值为 Belgium 的 Country 对象?我已经在这个问题上搜索了好几个小时,并阅读了 StackOverflow 上关于这个的每一篇文章,但似乎我没有找到丢失的链接......任何帮助(最好是使用此代码)表示赞赏!
对不起,这篇长文章,我尽量做到完整,否则我永远不会明白......
请您参考如下方法:
FXML 是 MVC pattern 的简单形式. FXML 文件是一个 View ,Controller 很明显,有什么遗漏?
模型 - 一个存储与当前 View 相关的所有数据的地方,因此,您可以使用它在 Controller 之间共享 Country 数据。
1. 引入模型的一种可能方法是“上下文”。让我们考虑一个案例,那么整个项目只有一个模型,因此您可以拥有 Singleton 形式的全局上下文。
public class Context {
private final static Context instance = new Context();
public static Context getInstance() {
return instance;
}
private Country country = new Country();
public Country currentCountry() {
return country;
}
}
您的 SampleController 将有以下更改:
@Override
public void initialize(URL url, ResourceBundle rb) {
Context.getInstance().currentCountry().setCountry("Belgium");
}
和
SubController1
可以用同样的方式访问它:
@Override
public void initialize(URL url, ResourceBundle rb) {
System.out.println(Context.getInstance().currentCountry().getCountry());
}
2. 另一种方法是将上下文传递给
SubController1
然后你加载它的xml。如果您不想拥有应用程序全局模型,它会更好地工作。因此,创建类似的 Context 类但没有实例字段,并且:
public class Sub1Controller implements Initializable {
private Context context;
public void setContext(Context context) {
this.context = context;
// initialize country dependent data here rather then in initialize()
}
}
在
SampleController
中设置上下文:
Context currentContext = new Context();
@Override
public void initialize(URL url, ResourceBundle rb) {
currentContext.currentCountry().setCountry("Belgium");
}
@FXML
private void handleButtonAction(ActionEvent event) throws IOException {
URL url = getClass().getResource("Sub1.fxml");
FXMLLoader fxmlloader = new FXMLLoader();
fxmlloader.setLocation(url);
fxmlloader.setBuilderFactory(new JavaFXBuilderFactory());
pContent.getChildren().clear();
pContent.getChildren().add((Node) fxmlloader.load(url.openStream()));
// here we go
((Sub1Controller)fxmlloader.getController()).setContext(currentContext);
}