JavaFX и Clojure: привязка наблюдаемых к неизменяемым объектам

Я пытался выяснить подход, который следует принять, чтобы позволить JavaFX TableView (или любой другой вещи JavaFX) представлять некоторые данные Clojure и позволять пользователю манипулировать данными через графический интерфейс.

Для этого обсуждения предположим, что у меня есть список / вектор карт, то есть что-то вроде [{:col1 "happy1" :col2 "sad1"} {:col1 "happy2" :col2 "sad2"}], и я хочу, чтобы он отображался в графической таблице следующим образом:

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

Довольно просто. Это было сделано миллионы раз в мировой истории.

Проблема в том, что TableView настаивает на взятии ObservableList и т. Д., Что по своей сути является изменчивым, как и все Observables в JavaFX. Это отлично подходит для поддержания таблицы в актуальном состоянии, а в изменяемой модели также отлично подходит для того, чтобы позволить пользователю напрямую манипулировать данными через графический интерфейс. Я не эксперт, но в этом случае кажется, что JavaFX хочет, чтобы объект GUI действительно содержал реальные данные. Мне это кажется смешным (не ха-ха). Чтобы поддерживать мою собственную модель и общаться между графическим интерфейсом пользователя и моделью через некоторый API или интерфейс, также подразумевается, что я поддерживаю данные в двух местах: в моей собственной модели и в графическом интерфейсе. Это правильный образ действий? Возможно, это нормально, поскольку графический интерфейс отображает только небольшую часть всех данных и позволяет моим данным модели быть просто обычными данными модели, а не экземпляром какого-либо типа, производного от Java.

Таким образом, это приводит к следующим трем общим вопросам при попытке поместить графический интерфейс в модель без сохранения состояния / неизменяемость:

  1. Каким образом модель может быть по-настоящему неизменной, если графический интерфейс обязательно позволяет вам что-то менять? Я специально думаю о каком-то инструменте дизайна, редакторе и т. Д., Где пользователь явно меняет вещи вокруг. Например, LightTable - это редактор, но история основана на неизменных данных. Как это может быть? Меня не интересует FRP для этого обсуждения.

  2. Предполагая, что на каком-то уровне существует хотя бы один Atom или другой изменяемый тип Clojure (ref / var / agent / и т. Д.) (Будь то один Atom, содержащий всю базу данных дизайна в памяти, или база данных проекта является неизменяемым списком mutable Atoms), какая из моделей [MVP, MCP, MVVM и т. д.] лучше всего подходит для этого типа создания?

  3. JavaFX засоряет иерархию классов всеми мыслимыми вариантами интерфейса Observable (http://docs.oracle.com/javafx/2/api/javafx/beans/Observable.html), с такими драгоценными камнями, как Observable[whatever]Value, включая, например, ObservableMap и ObservableMapValue, а затем десятки и десятки классов реализации, таких как IntegerProperty и SimpleIntegerProperty. .. блин! wtf ?. Предполагая, что мне нужно создать несколько объектов Clojure (defrecord и т. Д.) И реализовать некоторые Observable методы интерфейса на моих в основном неизменяемых объектах, могу ли я просто придерживаться Observable, или я должен реализовать каждый до конечного узла, то есть ObservableIntegerValue , и т.д.?

Каков правильный подход высокого уровня? Поддерживать один атом верхнего уровня, который заменяется каждый раз, когда пользователь меняет значение? Поддерживать тысячу низкоуровневых атомов? Позволить моим значениям жить как наблюдаемые объекты JavaFX и забыть о структурах данных Clojure? Реализовать мой собственный набор Observables в Clojure с использованием некоторого класса reify / proxy / gen, но реализовать их как неизменяемые, которые заменяются каждый раз при внесении изменений? Есть ли необходимость или место в функции Clojure add-watch? Я бы очень предпочел, чтобы мои данные были просто обычными данными в Clojure, а не «типом» или реализацией интерфейса чего-либо. Целое число должно быть целым числом и т. Д.

Благодарность


person Sonicsmooth    schedule 31.07.2014    source источник
comment
Может быть, это поможет: github.com/halgari/fn-fx, видео-введение здесь: youtube.com/watch?v=hJ8GZxhsaVQ   -  person Rodrigo Taboada    schedule 12.02.2015
comment
я думаю, что подход курсоров из страны ClojureScript также связан: github .com / reagent-project / reagent-cursor # cursors   -  person zarkone    schedule 25.04.2015
comment
Мне нечего добавить, о чем вы еще не задумывались, но: Некоторые библиотеки Java или некоторые методы в некоторых библиотеках Java легко использовать в Clojure, а некоторые нет. Некоторые проекты, которые вполне разумны в Java, противоречат намерениям дизайнеров Clojure. Использовать библиотеки с этими проектами будет некрасиво. Вы можете это сделать (у меня), но это не будет Clojurely. Очевидно, это все же может быть лучшим вариантом, чем написание новой библиотеки с нуля на Clojure.   -  person Mars    schedule 06.09.2015


Ответы (1)


Я бы добавил часы к атому, а затем обновил бы вашу наблюдаемую на основе diff. http://clojuredocs.org/clojure.core/add-watch

person Terje Dahl    schedule 08.02.2016