Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8103121

No MouseEvents reach the Scene after a dragged node is removed from the SceneGraph while dragging

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Fixed
    • Icon: P4 P4
    • 8
    • 7u25, 8
    • javafx

      Following test programm illustrates the issue:

      ========================

      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;
        }
      }

      ====================

      after the node is removed while dragging, no mouse events reach the scene anymore until the mouse is released. DragEvents still reach the removed node which is actually good because by this we can compensate the former issue.

            psafrata Pavel Ĺ afrata
            srheinnecjfx Sebastian Rheinnecker (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported: