Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaFX—数据模型类中的可观察集合_Java_Model View Controller_Collections_Javafx 2_Javafx - Fatal编程技术网

JavaFX—数据模型类中的可观察集合

JavaFX—数据模型类中的可观察集合,java,model-view-controller,collections,javafx-2,javafx,Java,Model View Controller,Collections,Javafx 2,Javafx,下面是一段简单的JavaFX代码,以说明我的问题 List list1 = new ArrayList(); list1.add("foo"); ... someListView = new ListView<>(); ObservableList someObservableList = FXCollections.observableList(list1); someListView.setItems(someObservableList); ... someObservab

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

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

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

someObservableList.add("bar");
List list1=new ArrayList();
清单1.添加(“foo”);
...
someListView=新建ListView();
ObservableList someObservableList=FXCollections.ObservableList(列表1);
setItems(someObservableList);
...
添加(“条”);
如果我理解正确,在调用
setItems
方法后,不仅列表的内容将显示在
ListView
Gui组件中,而且如果项目随后添加到
ObservableList
实例中,
ListView
将自动刷新,并自动显示新添加的项目,无需调用任何其他
add
refresh
方法

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

当然,在一个经典的Java应用程序中,应用程序的模型并不是由
ObservableCollection
实例组成的。因此,无论何时向模型添加内容,都必须更新从原始列表派生的
observebleLists
实例。显然这是不可避免的,对吗

这让我想知道,从现在起,修改模型类中的
集合
类型引用(例如
列表
集合
集合
可观察
,…)并用它们的
可观察集合
替换它们,这是一个聪明的主意吗


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

您可以通过Granite Data Services Generator(用groovy GSP和Java编写)来生成“bindable”通过生成javafx属性来保存基本字段(包括集合)的数据,可以从域类中提取java类

这方面有一个很好的示例项目:它是用maven构建的,启用了generation。这指的是枯燥的原则(不要重复自己),有时域类成为可绑定的似乎更有用。您已经修改了类,使其具有javafx属性:您已经做了类似于Granite的事情,是的,它有一些优点,因为它删除了样板代码(类似于此:EJB3似乎删除了DTO,实体是域类)。但是您的域类与视图紧密耦合:它看起来像MVC模式

另一个解决方案是使用JFXtras库,它有一个有趣的API,可以在java集合上动态生成监听器来实例化javafx属性。下面是一个链接,其中介绍:

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

我看到的最后一个解决方案是坚持MVP模式,实际上您正在使用它,它最初不允许通过视图访问模型类,因为它引入了一个Presenter层来链接这两个层:

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


我不认为有更好的解决办法:根据你的需要和喜好来选择。它甚至可以成为一场经典的MVC与MVP之争,没有赢家。

一般来说,我会在模型层避免任何GUI库依赖性。这将限制可能的重用。对于javafx依赖项以及在模型类中经常(错误地)使用的AWT对象(如点/矩形),情况也是如此

原因很简单:您的代码将自身局限于平台和框架,例如Android不支持上述任何JavaUI层,如awt。此外,ORM可能在处理此类类型时遇到问题,这些类型需要为您的域对象定制适配器

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

  • 使用*.fxml视图: 您必须使用javafx控制器,它只需创建到ViewModel的绑定
  • 使用代码生成视图: 只需在视图中将构造函数依赖项添加到所需的ViewModel中,并在视图中将其绑定到属性
ViewModels通常包含一些样板代码,您可能希望避免这些代码。然而,虚拟机也为您提供了一个施展魔法的机会,即使用反射自动生成那些列表+事件以进行ObservableCollection


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

此外,在模型中使用JavaFXObservables会增加对jfxrt.jar的直接依赖性,当模型是shar时,这可能会导致问题