Контекст: у меня есть приложение кроссворда на основе clojure, основным пользовательским интерфейсом которого является JTabbedPane с двумя вкладками, сеткой и таблицей подсказок. Таблица подсказок представляет собой представление вектора подсказок, но сам вектор не является официальным хранилищем данных, а динамически генерируется из пары внутренних структур данных с помощью функции (active-cluelist)
, запускаемой выбранной вкладкой подсказок.
Итак, это реализация таблицы подсказок:
(def cluelist [])
(def update-cluelist)
(def model)
(defn make []
(let [column-names ["Sq" "Word" "Clue"]
column-widths [48 200 600]
table-model (proxy [AbstractTableModel] []
(getColumnCount [] (count column-names))
(getRowCount [] (count cluelist))
(isCellEditable [row col] (= col 2))
(getColumnName [col] (nth column-names col))
(getValueAt [row col] (get-in cluelist [row col]))
(setValueAt [s row col]
(let [word (get-in cluelist [row 1])]
(add-clue word s) ; editing a cell updates the main clue data
(def cluelist (assoc-in cluelist [row 2] s))
(. this fireTableCellUpdated row col))))
table (JTable. table-model)
]
; some pure display stuff elided
(def model table-model)
)
(defn update-cluelist []
(def cluelist (active-cluelist))
(.fireTableDataChanged model))
Кто-то в другом обсуждении заметил, что для (update-cluelist)
основным запахом является ручной вызов fireTableDataChanged
, потому что ничто за пределами класса TableModel никогда не должно вызывать этот метод. Однако я считаю, что это неизбежное следствие динамической генерации таблицы из внешнего источника. Документы не слишком полезны - они утверждают, что
Ваш пользовательский класс просто должен вызвать один из следующих
Методы AbstractTableModel каждый раз, когда данные таблицы изменяются
внешний источник.
, который неявно предполагает, что класс CustomTableModel является официальным источником данных.
Также здесь есть некоторое несоответствие импеданса clojure / java - в java у меня были бы cluelist
и update-cluelist
частный член и метод моей TableModel, тогда как в clojure cluelist
и модели таблицы динамически изменяемые переменные, к которым update-cluelist
имеет доступ.
Моя главная проблема заключается в том, что вокруг не так много кода clojure / swing, на который я мог бы обратить внимание для получения лучших практик. У кого-нибудь есть советы, как лучше всего это сделать?