Drag Image outside the window with JavaFX

Hauke :

everybody,

I want to insert a graphic into my application that can be dragged and dropped out of the application. As soon as the graphic is released outside the window, an Undecoraded / Transparent window should be opened, where only this graphic is displayed.

    Stage newStage = new Stage();
    StackPane stack = new StackPane();
    ImageView imageView = new ImageView(new Image(this.getClass().getResourceAsStream(InBoxEnum.Graphic.INBOXLOGO.getFilename())));
    stack.getChildren().add(imageView);


    imageView.setOnDragDetected(event -> {
        Dragboard dragboard = imageView.startDragAndDrop(TransferMode.MOVE);

        dragboard.setDragView(imageView.snapshot(null, null));
        ClipboardContent content = new ClipboardContent();
        content.put(DRAGGABLE_INBOX_TYPE, "dontcare");
        dragboard.setContent(content);

        event.consume();
    });

    imageView.setOnDragDone(event -> {
        System.out.println(event.getScreenX());
        System.out.println(event.getScreenY());
    });

    Scene scene = new Scene(stack, 500, 500);
    newStage.setScene(scene);
    newStage.show();

The DragDetected event works so far also without problems.

The problem is that inside the dragDone event the position of the mouse is always 0 and I can't tell if the mouse is inside or outside my application. If the mouse is released inside the application, nothing should happen.

I also tried with Robot Class, but I always get a static strange x/y position.

I am using JAVA 11 (Adopt JDK).

Thanks for your help

fabian :

Using Robot works fine for me (Oracle JDK 11 + JavaFX 12). Since you don't actually want to drag&drop any image data, you could simply work around this issue by creating a new stage immediately and use the MOUSE_DRAGGED of the ImageView to update the position of the window:

Stage newStage = new Stage();
StackPane stack = new StackPane();
ImageView imageView = new ImageView(new Image(...));
stack.getChildren().add(imageView);

class DragHandler implements EventHandler<MouseEvent> {

    Stage dragTarget;

    @Override
    public void handle(MouseEvent event) {
        if (dragTarget != null) {
            // move stage
            dragTarget.setX(event.getScreenX());
            dragTarget.setY(event.getScreenY());
            event.consume();
        }
    }

}

final DragHandler dragHandler = new DragHandler();

imageView.setOnDragDetected(event -> {
    // init stage at half transparency
    Group root = new Group(new ImageView(imageView.getImage())); 
    root.setOpacity(0.5);

    Scene displayScene = new Scene(root);
    displayScene.setFill(null);
    Stage displayStage = new Stage();
    displayStage.initStyle(StageStyle.TRANSPARENT);
    displayStage.setScene(displayScene);
    displayStage.setX(event.getScreenX());
    displayStage.setY(event.getScreenY());
    displayStage.show();

    dragHandler.dragTarget = displayStage;

    event.consume();
});
imageView.setOnMouseDragged(dragHandler);
imageView.setOnMouseReleased(event -> {
    if (dragHandler.dragTarget != null) {
        if (stack.contains(event.getX(), event.getY())) { // check, if drop happened inside the bounds of the scene root
            dragHandler.dragTarget.hide();
        } else {
            // make stage fully opaque & cleanup
            dragHandler.dragTarget.getScene().getRoot().setOpacity(1);
            imageView.setImage(null);
        }
        dragHandler.dragTarget = null;
        event.consume();
    }
});

Scene scene = new Scene(stack, 500, 500);
newStage.setScene(scene);
newStage.show();

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=141147&siteId=1