JavaFX和Clojure:将observable绑定到不可变对象

时间:2014-07-31 22:08:14

标签: clojure javafx lighttable

我一直试图找出允许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只显示总数据的一小部分,它让我的模型数据只是普通的模型数据,而不是某些Java派生类型的实例。

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

  1. 如果GUI必然允许您更改内容,那么下面的模型如何真正不可变?我专门考虑某种设计工具,编辑器等,用户明确地改变一切。例如,LightTable是一个编辑器,但故事是它基于不可变数据。怎么会这样?我对此次讨论并不感兴趣。

  2. 假设在某种程度上至少有一个Atom或其他Clojure可变类型(ref / var / agent / etc)(无论是一个Atom包含整个in-内存设计数据库,或者设计数据库是否是可变Atoms的不可变列表,哪种[MVP,MCP,MVVM等]模型最适合这种类型的创建?

  3. JavaFX使用Observable接口(http://docs.oracle.com/javafx/2/api/javafx/beans/Observable.html)的每个可以想象的变体散布了类层次结构,其中包含Observable[whatever]Value这样的宝石,包括例如ObservableMap和{{1}然后,几十个实施类,如ObservableMapValueIntegerProperty ... geez! WTF?假设我必须创建一些Clojure对象(SimpleIntegerProperty等)并在我的大多数不可变对象上实现一些defrecord接口方法,我可以坚持Observable,或者必须我将每一个实现到叶节点,即Observable等?

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

    感谢

1 个答案:

答案 0 :(得分:2)

我会向原子添加一个监视器,然后根据差异更新你的observable。 http://clojuredocs.org/clojure.core/add-watch