下面是一段简单的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组件中显示列表内容,还会将项目添加到{{1}之后,ObservableList
会自动刷新并自动显示新添加的项目,而无需再调用任何其他ListView
或add
方法。
到目前为止,这么好。但是,如果我在原始列表中添加内容(即refresh
),该怎么办?这些更改不会自动传播。它很有道理,但有时候很不方便。
当然,在传统的Java应用程序中,应用程序的模型不包含list1
实例。因此,无论何时向模型添加内容,您都必须更新从原始列表派生的ObservableCollection
实例。显然这是不可避免的,对吗?
这让我想知道,修改ObservableLists
类型事件(例如Collection
,List
,Collection
,Set
,...是一个聪明的主意。 。)在Model类中,从现在开始用Iterable
个替换它们?
到目前为止,我总是认为这些ObservableCollection
类只应该在应用程序的Gui层中使用,但在任何地方使用它们似乎都很方便。
答案 0 :(得分: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(对于集合,它可能变得难以阅读恕我直言),这样您就不会修改您的域类成为View相关。但对于集合的高级绑定:它似乎不是最好的解决方案。它看起来像是MVC和MVP之间的妥协。
我看到的最后一个解决方案是坚持MVP模式,你实际上正在使用它,它最初不允许通过引入Presenter层来链接两者来访问Model类:http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter < / p>
您必须在javafx属性和域类之间手动实例化和同步值:有时它是您想要的并且是实现此目的的唯一方法(例如:这样您可以'恢复'到旧域值一个表单非常容易,如果它是可绑定的,你将失去最后一个'正确的'域值)。请注意,您可以将javafx属性放入单例(使用IOC框架,如Spring),以便通过不同的视图进行访问和绑定:我将它们视为Presenter的一部分。
我认为没有更好的解决方案:根据您的需求和您的喜好进行选择。它甚至可以成为MVC与MVP的经典辩论,但没有赢家。
答案 1 :(得分:6)
一般来说,我会避免模型层中的任何GUI库依赖关系。这将限制可能的重用。这对于javafx依赖项以及诸如Point / Rectangle之类的AWT对象都是如此,这些对象经常在模型类中使用(错误地)。
原因很简单:您的代码将自己局限于平台和框架,例如Android不支持任何提到的java UI层,例如awt。此外,ORM可能会遇到这类需要为域对象定制适配器的问题。
我发现使用MVVM模式的略微修改版本也适用于javafx。在您的示例中,您将使用普通List和相应的propertychange事件设计模型。然后,ViewModel将作为模型的适配器,提供视图可以绑定的ObservableList。
ViewModels通常包含一些样板代码,您可能希望避免这些代码。但是,VM也为您提供了一些魔术的机会,即使用反射自动生成那些List +事件到ObservableCollection。
关于MVC的最后一句话:Swing和javafx并不是设计用于MVC方式(因为控制器被合并到视图中)。 MVC适用于组件,因为MVP和MVVM更适合应用程序。