13

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

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

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

someObservableList.add("bar");

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

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

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

这让我想知道,从现在开始修改模型类中的Collection类型出现(例如,、、、List... CollectionSetIterable用它们的ObservableCollection替代品替换它们是一个聪明的主意吗?

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

4

2 回答 2

7

您可以通过 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 属性放在单例中(使用诸如 Spring 之类的 IOC 框架)以通过不同的视图进行访问和绑定:我将它们视为 Presenter 的一部分。

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

于 2013-11-06T13:17:36.053 回答
6

一般来说,我会在模型层中避免任何 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 更适合应用程序。

于 2013-11-09T14:09:09.760 回答