drag&drop events?

Magosányi Árpád m4gw4s at gmail.com
Tue Apr 30 08:02:26 UTC 2019


Hi list,

I am trying to implement drag&drop in a tree view. I actually did it. It
works. In 1/3rd of the times.
Otherwise there are times when relevant events do not arrive, and events
kick in from nowhere.

Specifically I don't see the dragDone event to fire, although I call
setDropCompleted(true) in the dragDropped event.

If I do hand testing, I just can't see much correlation between events
arriving and the mouse movements I do.
dragDropped events came out of nowhere, some cells receive
dragEnter/Exit/Over event, some not, the event source is set to
misterious values.

This is how I test (see
https://github.com/magwas/zenta3/blob/master/ui/src/test/java/org/rulez/demokracia/zenta3/editor/DragAndDropTest.java
for full code):

  @Test
  public void
      when_the_drag_is_dropped_the_element_is_moved(
          final FxRobot robot
      ) {
    final ZentaTreeCell startCell = findCellFor(newElement);
    robot.drag(startCell);
    final ZentaTreeCell targetCell = findCellFor(thing);
    final int targetIndex = targetCell.getIndex();
    robot.moveTo(targetCell);
    robot.dropTo(targetCell);
    WaitForAsyncUtils.waitForFxEvents();

    final ZentaTreeCell endCell = findCellFor(newElement);
    assertEquals(targetIndex + 1, endCell.getIndex());
  }

And these are the relevant lines of my TreeCell implementation (
https://github.com/magwas/zenta3/blob/master/ui/src/main/java/org/rulez/demokracia/zenta3/editor/tree/ZentaTreeCell.java
for full code):

public class ZentaTreeCell extends TreeCell<ZentaElement> {

  public static final DataFormat ZENTA_FORMAT =
      new DataFormat("Zenta Elements");
  private final TreeView<ZentaElement> treeView;

  public ZentaTreeCell(final TreeView<ZentaElement> view) {
    super();
    treeView = view;
    setOnDragDetected((e) -> dragDetected(e));
    setOnDragEntered((e) -> dragEntered(e));
    setOnDragOver((e) -> dragOver(e));
    setOnDragExited((e) -> dragExited(e));
    setOnDragDropped((e) -> dragDropped(e));
    setOnDragDone((e) -> dragDone(e));
  }

  private void dragDone(final DragEvent e) {
    System.out.println("done\n\tat " + this + "\n\t event: " + e);
  }

  private void dragDropped(final DragEvent e) {
    System.out.println("dropped\n\tat " + this + "\n\t event: " + e);
    e.setDropCompleted(true);
    e.getDragboard().clear();
    e.consume();
    getStyleClass().remove("dragtarget");
    final ZentaTreeCell gestureSource = (ZentaTreeCell)
e.getGestureSource();
    final ZentaTreeCell gestureTarget = (ZentaTreeCell)
e.getGestureTarget();

    final TreeItem<ZentaElement> draggedItem = gestureSource.getTreeItem();
    final TreeItem<ZentaElement> draggedItemParent =
draggedItem.getParent();
    final TreeItem<ZentaElement> droppeditem = gestureTarget.getTreeItem();
    final TreeItem<ZentaElement> droppedItemParent =
droppeditem.getParent();
    final int indexInParent =
        droppedItemParent.getChildren().indexOf(droppeditem);
    draggedItemParent.getChildren().remove(draggedItem);
    droppedItemParent.getChildren().add(indexInParent + 1, draggedItem);
    treeView.getSelectionModel().select(draggedItem);
  }

  private void dragOver(final DragEvent e) {
    System.out.println("over\n\tat " + this + "\n\t event: " + e);
    e.acceptTransferModes(TransferMode.MOVE);
    e.consume();
  }

  private void dragEntered(final DragEvent e) {
    System.out.println("entered\n\tat " + this + "\n\t event: " + e);
    getStyleClass().add("dragtarget");
    e.consume();
  }

  private void dragExited(final DragEvent e) {
    System.out.println("exited\n\tat " + this + "\n\t event: " + e);
    getStyleClass().remove("dragtarget");
    e.consume();
  }

  public void dragDetected(final MouseEvent e) {
    System.out.println("detected\n\tat " + this + "\n\t event: " + e);
    System.out.println("dragDetected");
    final Dragboard dragBoard = startDragAndDrop(TransferMode.MOVE);
    final Map<DataFormat, Object> map = new HashMap<>();
    final ZentaElement item = getItem();
    map.put(ZENTA_FORMAT, item);
    System.out.println("item: " + item);
    dragBoard.setContent(map);

    e.consume();
  }

  @Override
  public void updateItem(final ZentaElement item, final boolean empty) {
    super.updateItem(item, empty);
    if (empty) {
      setText(null);
      setGraphic(null);
      final ZentaElement currentItem = getItem();
      if (null != currentItem)
        currentItem.removePropertyChangeListener((e) -> propertyChanged(e));
      setItem(null);
    } else {
      setText(item.getName());
      item.addPropertyChangeListener((e) -> propertyChanged(e));
    }
    setItem(item);
  }

  private void propertyChanged(final PropertyChangeEvent e) {
    if (Folder.CHILDREN_PROPERTY.contentEquals(e.getPropertyName())) {
      final TreeItem<ZentaElement> item =
          new ZentaTreeItem((ZentaElement) e.getNewValue());
      final TreeItem<ZentaElement> folderItem = getTreeItem();
      if (!(folderItem instanceof ZentaTreeItem))
        return;
      final ZentaTreeItem folderCell = (ZentaTreeItem) folderItem;
      folderCell.getChildren().add(item);
    }
  }

}


I guess I am missing something here, but after reading all the
documentation about drag&drop, I don't see what.




More information about the openjfx-dev mailing list