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();