带有控制器的多个 FXML,共享对象
Posted
技术标签:
【中文标题】带有控制器的多个 FXML,共享对象【英文标题】:Multiple FXML with Controllers, share object 【发布时间】:2012-08-23 09:43:36 【问题描述】:大家晚安,
我已经找到了很多关于这个主题的帖子,但我仍然无法将对象从 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() 方法获取值为比利时的 Country 对象?我已经在这个问题上搜索了几个小时,并且阅读了 *** 上关于这个的每一篇文章,但似乎我没有找到缺失的链接......感谢任何帮助(最好是使用此代码)!
抱歉,帖子太长了,我尽量做到完整,否则我永远不会明白......
【问题讨论】:
【参考方案1】:通过使用 DataFX 的 Flow API,您可以使用 CDI 在控制器实例中注入数据:
http://www.guigarage.com/2014/03/datafx-8-nighthacking/ http://www.guigarage.com/2013/12/datafx-controller-framework-preview/ http://www.javafxdata.org【讨论】:
【参考方案2】:FXML 是MVC pattern 的简单形式。 FXML 文件是视图,Controller 很明显,漏掉了什么? 模型——存储与当前视图相关的所有数据的地方,因此,您可以使用它在控制器之间共享国家/地区数据。
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);
【讨论】:
感谢一百万次谢尔盖,终于明白了。这是我第一次必须创建一个大型应用程序,但我仍在为如何“构建”它而苦苦挣扎。我还有另一个安全问题想问,但我不确定这是否是合适的网站(与代码无关) 嗨,谢尔盖,很抱歉提出这个老话题。这仍然是一种魅力,但我想知道......有没有办法最大化节点对象(Node) fxmlloader.load(url.openStream())
的宽度和高度,使其绑定到窗格(pContent)的宽度和高度?跨度>
它应该自动工作,如果没有,最好在单独的问题中提供您的代码
它适用于小型项目,但通常这是一种不好的做法,请参阅***.com/questions/3151768/…
谢谢@SergeyGrinev 这对我来说很神奇。我需要在其他控制器上获取表格行值,在进行大量谷歌搜索后,您的回答帮助我做到了这一点。谢谢。以上是关于带有控制器的多个 FXML,共享对象的主要内容,如果未能解决你的问题,请参考以下文章
如何使用不同的 fxml 文件创建多个 javafx 控制器?