23

我一直在尝试找出允许 JavaFX TableView(或任何其他 JavaFX 事物)表示一些 Clojure 数据并允许用户通过 GUI 操作数据的方法。

对于本次讨论,假设我有一个地图列表/矢量,例如 [{:col1 "happy1" :col2 "sad1"} {:col1 "happy2" :col2 "sad2"}],我希望它显示在图形表中,如下所示:

mykey1      mykey2
------------------
happy1      sad1
happy2      sad2

很简单。这在世界历史上已经完成了无数次。

问题是 TableView 坚持要取一个 ObservableList 等,这本质上是一个可变的东西,JavaFX 中的所有 Observable 也是如此。这对于使表保持最新非常有用,并且在可变模型中,对于允许用户通过 GUI 直接操作数据也非常有用。我不是专家,但在这种情况下,JavaFX 似乎希望 GUI 对象实际包含真实数据。这对我来说似乎很有趣(不是哈哈)。维护我自己的模型并通过一些 API 或接口在 GUI 和模型之间进行通信也意味着我在两个地方维护数据:在我自己的模型中和在 GUI 中。这是正确的做事方式吗?也许这没关系,因为 GUI 只显示总数据的一小部分,它让我的模型数据只是普通的模型数据,

因此,当尝试将 GUI 置于无状态/不可变模型上时,这会导致以下三个一般问题:

  1. 如果 GUI 必须允许您更改事物,那么下面的模型如何才能真正不可变?我正在特别考虑某种设计工具、编辑器等,用户在其中明确地改变事物。例如 LightTable 是一个编辑器,但故事是它基于不可变数据。怎么会这样?我对这次讨论的 FRP 不感兴趣。

  2. 假设在某个级别上至少存在一个Atom或其他 Clojure 可变类型(ref/var/agent/etc)(无论是Atom包含整个内存设计数据库的单个,还是设计数据库是 mutable 的不可变列表Atoms) , [MVP, MCP, MVVM, etc.] 模型中哪一个最适合这种类型的创作?

  3. JavaFX 用 Observable 接口 ( http://docs.oracle.com/javafx/2/api/javafx/beans/Observable.html ) 的每一个可以想象的变体来散布类层次结构Observable[whatever]Value,其中包括ObservableMapObservableMapValue,以及然后是几十个实现类,比如IntegerPropertySimpleIntegerProperty......天哪!wtf?。假设我必须创建一些 Clojure 对象(defrecord等)并Observable在我的大部分不可变对象上实现一些接口方法,我可以坚持使用Observable,还是必须将每个方法都实现到叶节点,即ObservableIntegerValue等?

什么是正确的高级方法?维护一个每次用户更改值时都会被替换的顶级原子?维持一千个低级原子?让我的值作为 JavaFX Observables 存在,而忘记 Clojure 数据结构?使用一些 reify/proxy/gen-class 在 Clojure 中实现我自己的一组 Observables,但是将它们实现为每次更改时都会被替换的不可变对象?Clojure 的功能是否有需要或地方add-watch?我非常希望我的数据只是 Clojure 中的普通数据,而不是“类型”或任何接口的实现。整数应该是整数等。

谢谢

4

1 回答 1

2

我会在原子上添加一个手表,然后根据差异更新您的可观察对象。 http://clojuredocs.org/clojure.core/add-watch

于 2016-02-08T11:13:30.903 回答