我有以下接口1 FXML
<SplitPane>
<items>
<TableView prefHeight="200.0" prefWidth="200.0">
<columns>
<TableColumn prefWidth="75.0" text="User" />
<TableColumn prefWidth="75.0" text="Pass" />
</columns>
</TableView>
<fx:include source="Container.fxml"/>
</items>
</SplitPane>
Container.fxml它仅用于存储xml接口示例我用于在TabPanel上嵌入InputData.fxml,Test.fxml
接口3 InputData.xml我包含textField用户名和密码以及一个保存按钮。
我想问一下每次按下按钮保存,界面1表都可以获取值并从界面3的值更新
因为接口3输入data.xml没有直接嵌入到接口1中,所以只有在符合条件时才会出现。所以我无法将数据fxml直接传输到以下
DataModel model = new DataModel();
listController.initModel(model);
editorController.initModel(model);
menuController.initModel(model);
它在接口上如果可以请帮助我
答案 0 :(得分:2)
这里有两种方法。
您可以使用nested controllers技术将附带的FXML中的控制器注入到包含FXML的控制器中。那么&#34;外部控制器&#34;可以将模型传播到&#34;嵌套控制器&#34;。
所以,例如如果你有
<SplitPane xmlns="..." fx:controller="com.mycompany.MainController">
<items>
<TableView prefHeight="200.0" prefWidth="200.0">
<columns>
<TableColumn prefWidth="75.0" text="User" />
<TableColumn prefWidth="75.0" text="Pass" />
</columns>
</TableView>
<fx:include fx:id="container" source="Container.fxml"/>
</items>
</SplitPane>
假设Container.fxml
的控制器类是ContainerController
。然后你会这样做:
public class MainController {
private Model model ;
@FXML
private ContainerController containerController ; // name is fx:id with "Controller" appended
public void setModel(Model model) {
this.model = model ;
containerController.setModel(model);
// ...
}
// ...
}
当然
public class ContainerController {
private Model model ;
public void setModel(Model model) {
this.model = model ;
// ...
}
// ...
}
如果你有很多包含的FXML文件和控制器等,这可能会开始变得无法维护。在这种情况下,更好的方法可能是在控制器中初始化模型。构造函数,并使用controllerFactory
上的FXMLLoader
创建控制器,并将模型传递给构造函数。所以现在你的控制器看起来像:
public class MainController {
private final Model model ;
public MainController(Model model) {
this.model = model ;
}
public void initialize() {
// bind controls to model here...
}
}
和ContainerController
等类似。请注意,这比以前的版本要清晰得多,您必须担心在任意时间设置模型。在这里,您可以确保在执行控制器中的任何代码时设置它。
现在,在加载FXML时,FMXLLoader
需要一些神奇的功能才能正确创建控制器:
Model model = new Model();
FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml"));
Callback<Class<?>, Object> controllerFactory = (Class<?> type) -> {
try {
for (Constructor<?> c : type.getConstructors()) {
if (c.getParameterCount() == 1 && c.getParameterTypes()[0].equals(Model.class)) {
return c.newInstance(model);
}
}
// couldn't find constructor taking a model, just use default:
return type.newInstance();
} catch (Exception exc) {
exc.printStackTrace();
return null ;
}
};
loader.setControllerFactory(controllerFactory);
Parent root = loader.load();
// ...
请注意,通过<fx:include>
标记加载的FXML文件将使用与&#34;相同的控制器工厂,包括&#34; FXML文件。因此,这将自动将相同的模型传递给嵌套控制器。
最后,如果您真的做了很多这样的事情,您可能需要考虑使用依赖注入框架来管理模型的依赖关系。 Afterburner.fx是一个专用的JavaFX DI框架,然后一切都像
一样简单public class MainController {
@Inject
private Model model ;
public void initialize() {
// bind UI elements to model...
}
}
您也可以使用Spring或Guice。例如。使用Spring,将控制器配置为原型bean,将模型配置为单例bean,并编写控制器以使用afterburner.fx注入模型。然后你可以告诉FXMLLoader
使用Spring来创建带有
// Spring application context:
ApplicationContext appContext = ... ;
FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml"));
loader.setControllerFactory(appContext::getBean);
Parent root = loader.load();