Перетаскивание TornadoFX в TreeView

Я новичок в JavaFX и, следовательно, также в TornadoFX, поэтому, пожалуйста, потерпите меня.

У меня есть простое приложение на Java, но я хочу перенести его на Kotlin, и у меня возникают проблемы с поиском соответствующих механизмов в TornadoFX. У меня есть ListView, содержащий реализации IStoryItem, представляющие истории и главы. Я хочу иметь возможность перемещать главы и даже из одной истории в другую. TreeView в Java имеет следующую реализацию в вызове setCellFactory:

    tv.setCellFactory(new Callback<TreeView<IStoryItem>, TreeCell<IStoryItem>>() {
        @Override
        public TreeCell<IStoryItem> call(TreeView<IStoryItem> siTreeView) {
            TreeCell<IStoryItem> cell = new TreeCellStoryEditor();

            cell.setOnDragDetected((MouseEvent event) -> {
                // Don't drag Story nodes.
                if (cell.getItem() instanceof Story) return;

                Dragboard db = cell.startDragAndDrop(TransferMode.MOVE);

                // Put the Part on the dragboard
                // From: https://stackoverflow.com/a/30916660/780350
                ClipboardContent content = new ClipboardContent();
                content.put(objectDataFormat, cell.getItem());
                db.setContent(content);

                event.consume();
            });

            cell.setOnDragOver((DragEvent event) -> {
                if (event.getGestureSource() != cell && event.getDragboard().hasContent(objectDataFormat)) {
                    /* allow for moving */
                    event.acceptTransferModes(TransferMode.MOVE);
                }

                event.consume();
            });

            cell.setOnDragEntered((DragEvent event) -> {
                IStoryItem item = cell.getItem();
                if (item instanceof Story &&
                        event.getGestureSource() != cell &&
                        event.getDragboard().hasContent(objectDataFormat)) {
                    cell.setUnderline(true);
                }

                event.consume();
            });

            cell.setOnDragExited((DragEvent event) -> {
                cell.setUnderline(false);
                event.consume();
            });

            cell.setOnDragDropped((DragEvent event) -> {
                try {
                    Dragboard db = event.getDragboard();
                    boolean success = false;
                    if (db.hasContent(objectDataFormat)) {
                        Part droppedPart = (Part)db.getContent(objectDataFormat);
                        IStoryItem targetStoryItem = cell.getItem();

                        // Question: How to handle drops between leaf items or
                        // before the initial leaf or after the final leaf.
                        if (targetStoryItem instanceof Story) {
                            Story story = (Story) targetStoryItem;

                            updateStoryWith(droppedPart, story);
                            addPartTo(cell.getTreeItem(), droppedPart);
                            success = true;
                        }
                    }

                    event.setDropCompleted(success);
                    event.consume();
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
            });

            cell.setOnDragDone((DragEvent event) -> {
                if (event.getTransferMode() == TransferMode.MOVE) {
                    IStoryItem item = cell.getItem();
                    TreeItem<IStoryItem> ti = cell.getTreeItem();
                    TreeItem<IStoryItem> pti = ti.getParent();
                    pti.getChildren().remove(ti);

                    IStoryItem psi = pti.getValue();
                    // Remove the Part/Chapter from its previous Story
                    boolean removed = removePartFrom(psi, item);
                }
                event.consume();
            });

            cell.setEditable(true);

            return cell;
        };
    });

Я искал что-то подобное в TornadoFX, но не нашел ничего похожего на то, что оно будет работать. Я уже использую конструктор cellFormat, но не могу понять, как добавить в него обработчики событий. Из intellisense IntelliJ я вижу, что есть также построитель cellFactory, но я не уверен, как его использовать или как добавить к нему обработчики событий.


person melston    schedule 12.09.2017    source источник


Ответы (1)


Вы можете использовать точно такую ​​же технику в TornadoFX. Помните, TornadoFX просто применяет высокоуровневый API поверх JavaFX. Вы всегда можете без проблем получить доступ к базовому API JavaFX.

tv.setCellFactory {
    object : TreeCell<IStoryItem>() {
        init {
            setOnDragOver { event ->

            }
            setOnDragEntered { event ->

            }
            setOnDragExited { event ->

            }
            setOnDragDropped { event ->

            }
        }
    }
}
person Edvin Syse    schedule 13.09.2017
comment
Для меня это странный синтаксис. Метод setCellFactory принимает объект обратного вызова (с методом call). Как это перевести на то, что у вас здесь? - person melston; 13.09.2017
comment
@melston Это называется SAM Conversion (SAM = Single Abstract Method). Дополнительную информацию можно найти здесь: kotlinlang.org/docs/reference/java -interop.html#sam-conversions - person Ruckus T-Boom; 13.09.2017
comment
@RuckusT-Boom, из всех описаний конструкторов SAM, которые я видел, я бы подумал, что пример будет object: Callback {...} - person melston; 13.09.2017
comment
@melston Это выражение объекта (kotlinlang.org/docs/reference/), что эквивалентно анонимному экземпляру Java. Преобразование SAM предназначено для лямбда-выражений Java и будет использовать соответствующие оптимизации компилятора в Java › 8 (которые использует TornadoFX). - person Ruckus T-Boom; 13.09.2017
comment
@RuckusT-Boom, я узнаю выражение объекта. Но даже для объектных выражений требуется тип реализуемого объекта, в данном случае Callback, а не тип аргумента для SAM. - person melston; 13.09.2017
comment
А, я вижу ваше замешательство. Выражение объекта в коде Эдвина является возвращаемым значением обратного вызова, а не самим обратным вызовом. { ... } вокруг выражения объекта TreeCell — это преобразование SAM, переданное в setCellFactory, которое преобразуется в Callback<TreeView<IStoryItem>, TreeCell<IStoryItem>>. - person Ruckus T-Boom; 13.09.2017
comment
Давайте продолжим обсуждение в чате. - person Ruckus T-Boom; 13.09.2017