多个带有控制器的FXML,共享对象

29

大家晚上好,

我已经发现了很多关于这个话题的帖子,但是我仍然无法将一个对象从Controller1传递到Controller2。是否有完整的教程或一些示例项目可以做到这一点?

我已经走到了这一步,但卡住了:

Country类

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()中获取该国家对象。
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()方法来获取值为比利时的Country对象?我已经在StackOverflow上搜索了几个小时,并阅读了每篇帖子,但似乎我找不到缺失的链接...任何帮助(最好是使用此代码)都将不胜感激!对于这篇长文,我很抱歉,我试图尽可能详细,否则我将永远无法理解...
2个回答

54

FXML是MVC模式的简单形式。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。如果您不想拥有应用程序全局模型,则此方法更有效。因此,请创建类似的上下文类,但没有实例字段,并执行以下操作:

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
非常感谢Sergey,终于一切都清晰明了。这是我第一次需要创建一个大型应用程序,但我仍在苦苦挣扎如何“构建”它。 我还有另一个安全问题想要问,但我不确定这是否是正确的网站来问(它与代码无关)。 - Perneel
嗨Sergey,如您所请求的:http://stackoverflow.com/questions/14265697/bind-width-and-height-of-dynamically-loaded-fxml - Perneel
1
它可以在小项目中工作,但通常这是一种不好的做法,请参见https://dev59.com/BnA75IYBdhLWcg3wsraD。 - Sergey Grinev
@SergeyGrinev:你能帮我解决这个问题吗?http://stackoverflow.com/q/22243243/2722799 - Java Man
1
谢谢 @SergeyGrinev 这个对我非常有帮助。我需要在其他控制器中获取表格行的值,你的答案帮助我在大量的搜索之后成功实现了这一点。非常感谢你。 - Joseph
显示剩余8条评论

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接