Как реализовать перетаскивание нескольких строк в TreeTableView/TableView?

Я нашел пример перетаскивания для treetableview, но он работает только для одной строки. Я не смог найти никакой помощи для перетаскивания нескольких строк в дереве или таблице. Любая помощь будет оценена по достоинству.

Пример перетаскивания одной строки


person Khanjee    schedule 24.08.2016    source источник


Ответы (1)


Все, что вам нужно сделать, чтобы разрешить перетаскивание нескольких строк в вашем примере, — это поместить в буфер обмена массив данных, а не только данные. Итак, в примере, который вы связали, вы бы сделали это вместо этого:

row.setOnDragDetected(event -> {
   if (!row.isEmpty()) {
      Dragboard db = row.startDragAndDrop(TransferMode.MOVE);
      db.setDragView(row.snapshot(null, null));
      ClipboardContent cc = new ClipboardContent();

      // Here you provide the ClipboardContent instance with the selected indexes instead of just one index.
      cc.put(SERIALIZED_MIME_TYPE, new ArrayList<Integer>(getSelectionModel().getSelectedIndices()));
      db.setContent(cc);
      event.consume();
   }
});

Тогда вам просто нужно будет обработать все эти индексы в методе setOnDragDropped:

row.setOnDragDropped(event -> {
   Dragboard db = event.getDragboard();
   if (acceptable(db, row)) {
       // Get all indexes.
       ArrayList<Integer> indexes = (ArrayList<Integer>) db.getContent(SERIALIZED_MIME_TYPE);

       ObservableList<TreeItem> items = FXCollections.observableArrayList();    
       // Get the item on each index.
       for (int index : indexes) {
           items.add(tree.getTreeItem(index));
       }  

       // Modify the rest of the code commented out below to remove 
       // all items in your list and then add them your target.
       // item.getParent().getChildren().remove(item);
       // getTarget(row).getChildren().add(item);
       // event.setDropCompleted(true);
       // tree.getSelectionModel().select(item);

       event.consume();
   }            
});

Конечно, для начала вам нужно будет включить множественный выбор в своей таблице. Это делается путем выполнения table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);.

person Jonatan Stenbacka    schedule 24.08.2016
comment
Просто примечание: я думаю, что реализация ObservableList не сериализуема, поэтому я думаю (но не проверял это), что это не удастся с исключением времени выполнения. Вероятно, вам нужно сделать cc.put(SERIALIZED_MIME_TYPE, new ArrayList<Integer>(getSelectionModel().getSelectedIndices()));, а затем List<Integer> indexes = (List<Integer>) db.getContent(...);. - person James_D; 24.08.2016
comment
с одной стороны он сериализуется и помещается в доску для перетаскивания. проблема возникает, когда вы получаете его обратно из dragboard. ArrayList‹Integer› content = (ArrayList‹Integer›) db.getContent(SERIALIZED_MIME_TYPE); Исключение в потоке Поток приложения JavaFX java.lang.ClassCastException: java.util.ArrayList не может быть приведен к java.lang.Integer в application.TableTreeViewApp.lambda$7(TableTreeViewApp.java:254) - person Khanjee; 24.08.2016
comment
На самом деле, после некоторого расследования кажется, что ошибка действительно возникает, когда вы помещаете ее в ClipboardContent, выполняя cc.put(SERIALIZED_MIME_TYPE, new ArrayList<Integer>(tree.getSelectionModel().getSelectedIndices())); в row.setOnDragDetected. Пока не знаю, почему так происходит, но попробую разобраться. Может быть, кто-то еще может объяснить это. - person Jonatan Stenbacka; 24.08.2016
comment
Вы должны принять это как принятый ответ, пока он действительно не сработает! - person Jonatan Stenbacka; 24.08.2016
comment
проблема решена, когда ArrayList вводится повсеместно. спасибо Джонатан Стенбака и Джеймс_Д - person Khanjee; 24.08.2016
comment
Не могли бы вы отредактировать мой ответ, указав правильный код, или опубликовать его здесь, в комментарии, чтобы я мог отредактировать свой ответ! :) - person Jonatan Stenbacka; 24.08.2016
comment
ваш ответ не нужно редактировать. Я делал это неправильно. - person Khanjee; 24.08.2016