No events when drag target is removed from the scenegraph while dragging

Sebastian Rheinnecker sebastian.rheinnecker at yworks.com
Fri Aug 16 07:53:12 PDT 2013


Hello,

we're not sure if we are doing something wrong but in our testing we 
noticed a behavior of javafx event processing that is unfortunate.

I attached a SSCCE that shows the issue. In the application, an ellipse 
shape is following the mouse, and when you click and drag, a listener 
that is called upon MouseEvent.DRAG_DETECTED removes the drag target 
from the scene graph (in this case, the ellipse) and immediately places 
a newly created ellipse in the same place.
The issue is: as soon as the ellipse (the drag target) is removed from 
the scene graph, no events are fired anymore for the entire drag 
operation *at all*. The sample application binds listeners to the scene, 
the stage and to the window but no mouse events are received until the 
user releases the mouse button. This happens in JavaFX 2.x as well as 
JavaFX 8.

We'd like to know if this is the intented behavior or a bug and if there 
is a way to receive the missing mouse events somehow.

Thanks in advance and kind regards,
Sebastian Rheinnecker

-- 
Sebastian Rheinnecker
phone: +49 7071 9709050
fax: +49 7071 9709051

yWorks GmbH
Vor dem Kreuzberg 28
72070 Tuebingen
Germany
http://www.yworks.com
Managing Directors: Sebastian Müller, Michael Pfahler
Commercial Registry: Stuttgart, Germany, HRB 382340

-------------- next part --------------
package test;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.input.DragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

/**
 * In this test app, an ellipse is moved like a cursor at the mouse position. The ellipses position is updated by
 * a MouseEvent handler listening for the MouseEvent.MOUSE_MOVED and MouseEvent.MOUSE_DRAGGED.
 * A problem occurs when the child node on which the drag started (another ellipse in this example) is removed from
 * the stage during the drag gesture. In this case, no further MOUSE_DRAGGED events are reported.
 */
public class MouseEventTest extends Application {

  private Stage primaryStage;

  public static void main(String[] args) {
    launch(args);
  }

  @Override
  public void start(final Stage primaryStage) {
    this.primaryStage = primaryStage;
    Scene scene = new Scene(createPane(), 600, 600);

    primaryStage.setTitle("MouseEvent Test App");
    primaryStage.setScene(scene);
    primaryStage.show();
  }

  private Parent createPane() {
    final Group contentGroup = new Group();

    // the cursor that is updated on mouse move and mouse drag
    final Ellipse cursor = new Ellipse(0, 0, 10, 10);
    cursor.setFill(Color.ORANGE);
    cursor.setMouseTransparent(true);

    contentGroup.addEventFilter(MouseEvent.ANY, new EventHandler<MouseEvent>() {
      @Override
      public void handle(MouseEvent mouseEvent) {
        if (MouseEvent.MOUSE_MOVED.equals(mouseEvent.getEventType())
            || MouseEvent.MOUSE_DRAGGED.equals(mouseEvent.getEventType())) {
          cursor.setLayoutX(mouseEvent.getX());
          cursor.setLayoutY(mouseEvent.getY());
        }
      }
    });

    // a background
    contentGroup.getChildren().add(new Rectangle(600, 600, Color.BLUE));

    // a child that gets removed later
    contentGroup.getChildren().add(createChild());

    // the cursor
    contentGroup.getChildren().add(cursor);

    return contentGroup;
  }

  // creates an ellipse that removes itself from its parent on MouseEvent.DRAG_DETECTED and replaces itself by another
  // ellipse
  private Node createChild() {
    final Ellipse ellipse = new Ellipse(300, 300, 200, 200);
    ellipse.addEventHandler(MouseEvent.DRAG_DETECTED, new EventHandler<MouseEvent>() {
      @Override
      public void handle(MouseEvent mouseEvent) {
        Group parent = (Group) ellipse.getParent();
        parent.getChildren().remove(ellipse);
        parent.getChildren().add(1, createChild());

        // none of this approaches work; no one receives mouse / drag events anymore!

        // window

        primaryStage.getScene().getWindow().addEventFilter(MouseEvent.ANY, new EventHandler<MouseEvent>() {
          @Override
          public void handle(MouseEvent mouseEvent) {
            System.out.println(mouseEvent);
          }
        });
        primaryStage.getScene().getWindow().addEventFilter(DragEvent.ANY, new EventHandler<DragEvent>() {
          @Override
          public void handle(DragEvent dragEvent) {
            System.out.println(dragEvent);
          }
        });

        // stage

        primaryStage.getScene().addEventFilter(MouseEvent.ANY, new EventHandler<MouseEvent>() {
          @Override
          public void handle(MouseEvent mouseEvent) {
            System.out.println(mouseEvent);
          }
        });
        primaryStage.getScene().addEventFilter(DragEvent.ANY, new EventHandler<DragEvent>() {
          @Override
          public void handle(DragEvent dragEvent) {
            System.out.println(dragEvent);
          }
        });

        // scene

        primaryStage.addEventFilter(MouseEvent.ANY, new EventHandler<MouseEvent>() {
          @Override
          public void handle(MouseEvent mouseEvent) {
            System.out.println(mouseEvent);
          }
        });
        primaryStage.addEventFilter(DragEvent.ANY, new EventHandler<DragEvent>() {
          @Override
          public void handle(DragEvent dragEvent) {
            System.out.println(dragEvent);
          }
        });
      }
    });
    return ellipse;
  }
}


More information about the openjfx-dev mailing list