Javafx从另一个FXML更新tableview

时间:2016-10-27 15:45:37

标签: uitableview javafx fxml

参考文章Applying MVC With JavaFx

我有以下接口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);

它在接口上如果可以请帮助我

1 个答案:

答案 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文件。因此,这将自动将相同的模型传递给嵌套控制器。

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