Javafx 从另一个 FXML 更新一个表视图
Javafx Update a tableview from another FXML
参考文章
我有接口 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 我包含用户名和密码的文本字段以及一个保存按钮。
想请问每次按下按钮save the,interface 1 table 可以从interface 3
的value中取值和update
因为界面3输入data.xml没有直接嵌入到界面1里面才出现eligible.So我不能直接传数据fxml到下面
DataModel model = new DataModel();
listController.initModel(model);
editorController.initModel(model);
menuController.initModel(model);
它在界面上,如果可以的话请帮助我
这里有两种方法。
将模型传递给嵌套控制器
您可以使用 nested controllers 技术将包含的 FXML 中的控制器注入到包含 FXML 的控制器中。然后 "outer controller" 可以将模型传播到 "nested controller"。
所以,例如如果你有
<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
的控制器 class 是 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 文件和控制器等,这可能会开始变得无法维护。在这种情况下,更好的方法可能是在控制器的构造函数中初始化模型,并在 FXMLLoader
上使用 controllerFactory
来创建控制器,并将模型传递给构造函数。所以现在你的控制器看起来像:
public class MainController {
private final Model model ;
public MainController(Model model) {
this.model = model ;
}
public void initialize() {
// bind controls to model here...
}
}
和 ContainerController
等类似。请注意,这比以前的版本要干净得多,在以前的版本中,您不必担心模型会在任意时间设置。在这里,您可以保证在执行控制器中的任何代码时设置它。
现在您需要一点魔法才能让 FMXLLoader
在加载 FXML 时正确创建控制器:
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 文件将使用与 "including" FXML 文件相同的控制器工厂。所以这会自动将相同的模型传递给嵌套控制器。
使用 DI 框架
最后,如果你真的做了很多这样的事情,你可能要考虑使用依赖注入框架来为你管理模型的依赖关系。 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();
参考文章
我有接口 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 我包含用户名和密码的文本字段以及一个保存按钮。
想请问每次按下按钮save the,interface 1 table 可以从interface 3
的value中取值和update因为界面3输入data.xml没有直接嵌入到界面1里面才出现eligible.So我不能直接传数据fxml到下面
DataModel model = new DataModel();
listController.initModel(model);
editorController.initModel(model);
menuController.initModel(model);
它在界面上,如果可以的话请帮助我
这里有两种方法。
将模型传递给嵌套控制器
您可以使用 nested controllers 技术将包含的 FXML 中的控制器注入到包含 FXML 的控制器中。然后 "outer controller" 可以将模型传播到 "nested controller"。
所以,例如如果你有
<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
的控制器 class 是 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 文件和控制器等,这可能会开始变得无法维护。在这种情况下,更好的方法可能是在控制器的构造函数中初始化模型,并在 FXMLLoader
上使用 controllerFactory
来创建控制器,并将模型传递给构造函数。所以现在你的控制器看起来像:
public class MainController {
private final Model model ;
public MainController(Model model) {
this.model = model ;
}
public void initialize() {
// bind controls to model here...
}
}
和 ContainerController
等类似。请注意,这比以前的版本要干净得多,在以前的版本中,您不必担心模型会在任意时间设置。在这里,您可以保证在执行控制器中的任何代码时设置它。
现在您需要一点魔法才能让 FMXLLoader
在加载 FXML 时正确创建控制器:
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 文件将使用与 "including" FXML 文件相同的控制器工厂。所以这会自动将相同的模型传递给嵌套控制器。
使用 DI 框架
最后,如果你真的做了很多这样的事情,你可能要考虑使用依赖注入框架来为你管理模型的依赖关系。 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();