为每个人服务,
我已经在这个主题上找到了很多帖子,但我仍然无法将一个对象从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)。其中包含一个边框窗格,顶部面板中有一个菜单栏,中间有一个内容窗格。在初始化时,我创建一个新的Country对象并将其存储在全局变量中。我有一个方法在单击菜单项时将另一个FXML加载到内容窗格中:
SampleController.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对象:
Sub1Controller.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上的每一篇文章,但似乎我没有找到缺失的链接...任何帮助(最好使用此代码)表示赞赏!
对于长篇文章感到抱歉,我尽量做到尽可能完整但我永远不会理解...
答案 0 :(得分:47)
FXML是MVC pattern的一种简单形式。 FXML文件是一个视图,控制器很明显,错过了什么? 模型 - 存储与当前视图相关的所有数据的位置,因此可用于在控制器之间共享国家/地区数据。
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);
}
答案 1 :(得分:3)
通过使用DataFX的Flow API,您可以使用CDI在控制器实例中注入数据: