【问题标题】:JavaFX - Observable Collections in the data model classesJavaFX - 数据模型类中的可观察集合
【发布时间】:2013-11-14 13:58:06
【问题描述】:

下面是一段简单的 JavaFX 代码来说明我的问题。

List list1 = new ArrayList();
list1.add("foo");
...

someListView = new ListView<>();
ObservableList someObservableList = FXCollections.observableList(list1);
someListView.setItems(someObservableList);
...

someObservableList.add("bar");

如果我理解正确的话,在调用setItems方法之后,不仅列表的内容会显示在ListView Gui组件中,而且如果之后在ObservableList实例中添加项目,@ 987654325@会自动刷新并自动显示新添加的项目,无需调用任何额外的addrefresh方法。

到目前为止,一切都很好。但是如果我在原始列表中添加一些东西(即list1)怎么办。这些更改不会自动传播。这很有意义,但有时很不方便。

当然,在经典的 Java 应用程序中,应用程序的模型不包含 ObservableCollection 实例。因此,无论何时向模型添加内容,都必须更新从原始列表派生的 ObservableLists 实例。显然这是不可避免的,对吧?

这让我想知道,在 Model 类中修改 Collection 类型出现(例如 ListCollectionSetIterable...)并将它们替换为从现在开始他们的ObservableCollection 替代品?

到目前为止,我一直认为这些ObservableCollection 类应该只用于应用程序的 Gui 层,但在任何地方使用它们似乎都很方便。

【问题讨论】:

    标签: java model-view-controller collections javafx-2 javafx


    【解决方案1】:

    一般来说,我会在模型层中避免任何 GUI-Library 依赖项。这将限制可能的重用。这对于 javafx 依赖项以及 AWT 对象(例如 Point / Rectangle)都是如此,这些对象在模型类中经常(错误地)使用。

    原因很简单:您的代码将限制在平台和框架上,例如 Android 不支持任何提到的 java UI 层,例如 awt。此外,ORM 可能会遇到需要为您的域对象自定义适配器的此类类型的问题。

    我发现使用MVVM 模式的略微修改版本也适用于javafx。在您的示例中,您将使用普通 List 和适当的 propertychange 事件来设计您的模型。然后,ViewModel 将作为您的模型的适配器,提供视图可以绑定到的 ObservableList。

    • 使用 *.fxml 视图: 您必须使用 javafx 控制器,它只会创建与 ViewModel 的绑定
    • 使用代码生成视图: 只需在视图中将构造函数依赖项添加到所需的 ViewModel 并在视图中绑定到属性。

    ViewModel 通常包含一些样板代码,您可能希望避免使用这些代码。然而,VM 也让你有机会做一些魔法,即使用反射来自动生成那些 List + Events 到 ObservableCollection。

    关于 MVC 的最后一句话:Swing 和 javafx 并非设计用于以 MVC 方式使用(因为控制器已合并到视图中)。 MVC 适合组件,而 MVP 和 MVVM 更适合应用程序。

    【讨论】:

      【解决方案2】:

      您可以破解 Granite 数据服务生成器(用 groovy GSP 和 Java 编写),通过生成 javafx 属性来保存包括集合在内的基本字段的数据,从而从您的域类生成“可绑定”java 类。

      有一个很棒的示例项目:https://github.com/graniteds/shop-admin-javafx,它是用 maven 构建的,并且启用了生成。这指的是 DRY 原则(不要重复自己),有时域类变成可绑定的似乎更有用。您已经修改了类以具有 javafx 属性:您已经完成了类似于 Granite 的操作,是的,它具有一些优点,因为它删除了样板代码(类似于此:EJB3 似乎删除了 DTO,实体是域类)。但是您的域类与您的视图紧密耦合:它看起来像 MVC 模式。

      另一个解决方案是使用 JFXtras 库,它有一个有趣的 API,可以在 java 集合上动态生成侦听器来实例化 javafx 属性。这是描述它的链接:http://ugate.wordpress.com/2012/07/30/javafx-programmatic-pojo-expression-bindings-part-iii/

      使用 JFXtras,您可以仅在需要时使用属性,使用相对简单的 API(对于集合,恕我直言,可能难以阅读),这样您就不会修改不会修改的域类成为视图相关。但是对于集合的高级绑定:它似乎不是最好的解决方案。这看起来像是 MVC 和 MVP 之间的折衷方案。

      我看到的最后一个解决方案是坚持使用 MVP 模式,您实际上是在使用它,它原本不允许通过 View 访问 Model 类,方法是通过引入 Presenter 层来链接两者:http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter

      您必须在 javafx 属性和域类之间手动实例化和同步值:有时这是您想要的,也是实现此目的的唯一方法(例如:这样您可以“恢复”到旧的域值一个很容易的表单,如果它是可绑定的,您将丢失最后一个“正确”域值)。请注意,您可以将 javafx 属性放在单例中(使用 IOC 框架,例如 Spring),以便通过不同的视图访问和绑定:我将它们视为 Presenter 的一部分。

      我认为没有更好的解决方案:根据您的需求和偏好进行选择。它甚至可以成为没有赢家的经典 MVC 与 MVP 辩论。

      【讨论】:

      • 此外,在模型中使用 JavaFX Observable 会立即增加对 jfxrt.jar 的依赖,当模型与其他非 JavaFX 项目共享时可能会导致问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      • 2016-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多