Фабрика ячеек TornadoFX TreeView не вызывается

Это связано с моим предыдущим вопросом.

У меня есть TreeView в центральной панели макета BorderPane. Этот TreeView заполняется выбором элемента из списка на левой панели. Вид в центре выглядит так:

class CenterView : View() {
    override val root = TreeView<IStoryItem>()
    init {
        with(root) {
            root = TreeItem(controller.storySet)

            setCellFactory {
                object : StoryEditorCell() {
                    init {
                        System.out.println("Creating StoryEditorCell")
                        onDragDetected = EventHandler {...}
                        onDragOver= EventHandler {...}
                        onDragEntered= EventHandler {...}
                        ...
                    }
                }
            }
            cellFormat { ... }
            populate { ... }
        }
    }
}

Функция setCellFactory вызывается, но по какой-то причине init самой фабрики никогда не вызывается. Поэтому мои обработчики перетаскивания никогда не настраиваются, а мой TreeCell имеет неправильный тип.

Формат ячейки правильный, и TreeView заполнено правильно, так что часть работает правильно. Что еще нужно сделать, чтобы получить правильную клеточную фабрику?


person melston    schedule 13.09.2017    source источник
comment
Это потому, что cellFormat перезаписывает ваш cellFactory. Вы не должны использовать setCellFactory И cellFormat. Вместо этого переопределите updateItem внутри фабрики ячеек. Сегодня я дам лучший ответ, а также добавлю API для DND в TornadoFX, чтобы вы могли комбинировать его с cellFormat.   -  person Edvin Syse    schedule 14.09.2017


Ответы (1)


Вызов cellFormat фактически создает CellFactory, поэтому он эффективно перезапишет вашу конфигурацию пользовательской фабрики, поэтому ваши обратные вызовы никогда не будут привязаны к ячейке, используемой в вашем TreeView.

Если вы вручную вызываете setCellFactory, вы должны избегать cellFormat и вместо этого переопределять updateItem внутри ячейки, чтобы настроить текст и графику ячейки.

Я рассматривал реализацию пользовательской поддержки DND, чтобы вы могли комбинировать cellFormat с DND без необходимости создавать собственную фабрику ячеек, но, к сожалению, у меня нет времени, чтобы начать это прямо сейчас. Если вы считаете текущий подход громоздким, пожалуйста, создайте задачу на GitHub, и мы займемся этим как можно скорее :)

А пока удалите вызов cellFormat, и все будет хорошо :) Помните правила переопределения updateItem: вызовите super, очистите текст/графику, если !empty и у вас есть значение, назначьте его тексту и/или графике.

Кроме того, не делайте onDragDetected = EventHandler {...}, вместо этого делайте setOnDragDetected {...}.

person Edvin Syse    schedule 14.09.2017
comment
Благодарю. Я не знал об этом немного о cellFormat. Я внесу изменения. Хранить их отдельно удобно, потому что они концептуально предназначены для разных вещей. И я использую пользовательский тип ячейки, настроенный для редактирования содержимого с помощью собственного updateItem. Думаю, мне придется объединить все это в одну вещь. Я думаю, что могу удалить материал cellFactory и напрямую поместить его в класс пользовательской ячейки. Я предполагаю, что изменение с onDragDetected EventHandler{...} на setOnDragDetected {...} связано с использованием свойств в TornadoFX. - person melston; 14.09.2017
comment
Упс. Я понял, что мне все еще нужна фабрика ячеек для создания пользовательского типа ячейки. Я также перенесу материал cellFormat в пользовательский класс ячеек. - person melston; 14.09.2017
comment
ХОРОШО. Перетаскивание работает. У меня нет своего форматирования, но это мелочь. Мне также пришлось отказаться от использования пользовательской ячейки для редактирования имен элементов, отображаемых в дереве, потому что я получал NPE при вызове super.updateItem(item, empty). Не уверен, почему это происходило, когда это работало на Java. - person melston; 14.09.2017
comment
Можете ли вы опубликовать полный код и, возможно, трассировку стека? Очень странно, если вызов super вызывает исключения. - person Edvin Syse; 15.09.2017
comment
Ну, ... я на самом деле перешел к другому подходу. Сейчас я использую TextFieldTreeCell и работаю с определенным типом узла, используя пользовательский StringConverter. Мне пришлось бы сделать резервную копию и попытаться найти, какой коммит показал проблему. Но у меня была пользовательская ячейка, унаследованная от TreeCell<IStoryItem> (в моем случае), и мой метод обновления был объявлен как override fun updateItem(item: IStoryItem, empty: Boolean). Первое, что сделал этот метод, это вызвал super.updateItem(item, empty), и именно здесь произошло NPE. - person melston; 15.09.2017
comment
И, насколько я помню, казалось, что NPE был из-за того, что метод updateItem не мог быть найден. - person melston; 15.09.2017