Skip to main content
 首页 » 编程设计

controller之带有 Controller 的多个 FXML,共享对象

2024年10月25日13insus

大家晚上好,

我已经找到了很多关于这个主题的帖子,但我仍然无法将对象从 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); 
}