1
votes

In my JavaFX application I support drag and drop either from OS to my app, either from inside the app. The following behavior is what I would like to accomplish:

  • If the user starts dragging from inside my app and he leaves my main window with the mouse (leaving my app), I would like to cancel the drag action, so even if he comes back with the cursor, he does not fire any dragover events (for example).

I believe I have to trigger some event of some kind on dragExitted on my main window.Is there any way to achieve this?

1
Maybe, if the dragged exit the bounds of the app consume event?Sedrick
Even if I consume the event, I'm consuming just the dragExitted event....it doesn't cancel the drag action. When it comes back, it will still trigger "dragEntered", "dragOver" and "dragDropped"Robert
Just a guess: clear the dragboard on mouse exit?James_D
Yes, tried this, but it still triggers the mentioned events, it just doesn't drop anything if the mouse is released. Visually the user still sees that he's dragging something.Robert

1 Answers

1
votes

Here is something you can play with. I think it does what you need.

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.input.*;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.scene.text.*;
import javafx.stage.Stage;

/**
 *
 * @author blj0011
 */
public class ConsumeDragEvent extends Application
{

    @Override
    public void start(Stage primaryStage)
    {

        final Text source = new Text(50, 100, "DRAG ME");
        final Text target = new Text(300, 100, "DROP HERE");

        final boolean[] hasBeenOffScreen = {false};




        source.setOnDragDetected(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                /* drag was detected, start a drag-and-drop gesture*/
                /* allow any transfer mode */
                hasBeenOffScreen[0] = false;
                Dragboard db = source.startDragAndDrop(TransferMode.ANY);

                ((Node) event.getSource()).setCursor(Cursor.HAND);
                /* Put a string on a dragboard */
                ClipboardContent content = new ClipboardContent();
                content.putString(source.getText());
                db.setContent(content);

                event.consume();
            }
        });        


        source.setOnDragDone(new EventHandler<DragEvent>() {
            @Override
            public void handle(DragEvent event) {
                /* the drag and drop gesture ended */
                /* if the data was successfully moved, clear it */
                if (event.getTransferMode() == TransferMode.MOVE) {
                    source.setText("");
                }
                event.consume();
            }
        });


        target.setOnDragOver(new EventHandler<DragEvent>() {
            @Override
            public void handle(DragEvent event) {
                /* data is dragged over the target */
                /* accept it only if it is not dragged from the same node 
                 * and if it has a string data */
                if (event.getGestureSource() != target &&
                        event.getDragboard().hasString()) {
                    /* allow for moving */
                    event.acceptTransferModes(TransferMode.MOVE);
                }

                event.consume();
            }
        });

        target.setOnDragEntered(new EventHandler<DragEvent>() {
            @Override
            public void handle(DragEvent event) {
            /* the drag-and-drop gesture entered the target */
            /* show to the user that it is an actual gesture target */
                 if (event.getGestureSource() != target &&
                         event.getDragboard().hasString()) {
                     target.setFill(Color.GREEN);
                 }

                 event.consume();
            }
        });

        target.setOnDragExited(new EventHandler<DragEvent>() {
            @Override
            public void handle(DragEvent event) {
                /* mouse moved away, remove the graphical cues */
                target.setFill(Color.BLACK);

                event.consume();
            }
        });

        target.setOnDragDropped(new EventHandler<DragEvent>() {
            @Override
            public void handle(DragEvent event) {
                /* data dropped */
                /* if there is a string data on dragboard, read it and use it */
                System.out.println(hasBeenOffScreen[0]);
                if(hasBeenOffScreen[0] == true)
                {
                    event.setDropCompleted(false);

                }
                else
                {
                    Dragboard db = event.getDragboard();
                    boolean success = false;
                    if (db.hasString()) {
                       target.setText(db.getString());
                       success = true;
                    }
                    /* let the source know whether the string was successfully 
                     * transferred and used */
                    event.setDropCompleted(success);
                }


                event.consume();
             }
        });


        Pane root = new Pane();
        root.getChildren().addAll(source, target);

        Scene scene = new Scene(root, 500, 500);
//        scene.setOnDragOver(event -> {
//            
//                scene.setCursor(Cursor.DEFAULT);
//                System.out.println(event.getX());
//                System.out.println(scene.getX());
//                System.out.println(scene.getWidth());
//                
//                if(event.getX() >= scene.getWidth())
//                {
//                    System.out.println("Out of scene!");
//                   // Dragboard db = source.startDragAndDrop(TransferMode.ANY);
//                     hasBeenOffScreen[0] = true;
//                    event.consume();
//                }
//          });     

        scene.setOnDragExited(event ->{
            hasBeenOffScreen[0] = true;
            System.out.println("Off scene!");

        });
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    class Delta{double x, y;}
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {
        launch(args);
    }

}