Javafx从另一个FXML更新表视图 [英] Javafx Update a tableview from another FXML
问题描述
参考文章通过JavaFx应用MVC
我具有以下接口1 FXML
I have interface 1 FXML the following
<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接口示例,我曾将InputData.fxml,Test.fxml嵌入到TabPanel上
Container.fxml it is only used to store xml interface example I used to embed InputData.fxml,Test.fxml on TabPanel
接口3 InputData.xml我包含textField用户名和密码以及一个保存按钮.
And interface 3 InputData.xml I contains textField the username and password and a save button.
我想问一下,每按一次按钮保存一次,接口1表可以获取值并从接口3的值进行更新
I would like to ask every time I press the button save the,interface 1 table can get value and update from the value of the interface 3
由于接口3输入的data.xml没有直接嵌入接口1中,因此只有在符合条件的情况下才会显示.因此,我无法将数据fxml直接传输到以下内容
Because the interface 3 Input data.xml not embedded directly into the interface 1 it only appears when eligible.So I can not transfer data fxml directly to the following
DataModel model = new DataModel();
listController.initModel(model);
editorController.initModel(model);
menuController.initModel(model);
如果可以的话请在界面上帮助我
It on the interface if can do please help me
推荐答案
此处有两种方法.
You can inject the controller from the included FXML into the controller for the including FXML using the nested controllers technique. Then the "outer controller" can propagate the model to the "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
的控制器类为ContainerController
.然后您会这样做:
Suppose the controller class for Container.fxml
is ContainerController
. Then you would do:
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
来创建将模型传递给构造函数的控制器.所以现在您的控制器看起来像:
Using a controller factory
If you have a lot of included FXML files and controllers, etc, this can start to get unmaintainable. In that case, a better approach might be to initialize the model in the controllers' constructors, and to use a controllerFactory
on the FXMLLoader
to create controllers with a model passed to the constructor. So now you controllers look like:
public class MainController {
private final Model model ;
public MainController(Model model) {
this.model = model ;
}
public void initialize() {
// bind controls to model here...
}
}
,对于ContainerController
等类似.请注意,这比以前的版本要干净得多,在以前的版本中,您必须担心在任意时间设置模型.在这里,您可以确保在执行控制器中的任何代码时将其设置.
and similarly for ContainerController
, etc. Note this is much cleaner than the previous versions, where you had to worry about the model being set at an arbitrary time. Here you're guaranteed it is set when any code in the controller is executed.
现在,在加载FXML时,FMXLLoader
需要一些魔术才能正确创建控制器:
Now you need a bit of magic for the FMXLLoader
to create the controllers correctly when the FXML is loaded:
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文件将使用与"includes" FXML文件相同的控制器工厂.因此,这将自动将相同的模型传递给嵌套控制器.
Note that FXML files loaded via an <fx:include>
tag will use the same controller factory as the "including" FXML file. So this will automatically pass the same model to the nested controller.
最后,如果您确实做了很多事情,则可能要考虑使用依赖项注入框架来为您管理模型上的依赖项. Afterburner.fx 是专用的JavaFX DI框架,然后一切都变得简单
Finally, if you really do a lot of this, you might want to consider using a dependency inject framework to manage the dependencies on the model for you. Afterburner.fx is a dedicated JavaFX DI framework, and then everything is as simple as
public class MainController {
@Inject
private Model model ;
public void initialize() {
// bind UI elements to model...
}
}
您还可以使用Spring或Guice.例如.使用Spring,将控制器配置为原型Bean,将模型配置为单例Bean,然后像afterburner.fx一样编写控制器以注入模型.然后,您可以告诉FXMLLoader
使用Spring使用
You can also use Spring or Guice. E.g. with Spring, configure the controllers as prototype beans, the model as a singleton bean, and write the controllers to inject the model as with afterburner.fx. Then you can tell an FXMLLoader
to use Spring to create the controllers with
// Spring application context:
ApplicationContext appContext = ... ;
FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml"));
loader.setControllerFactory(appContext::getBean);
Parent root = loader.load();
这篇关于Javafx从另一个FXML更新表视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!