Все ,

Я хочу вставить графическое изображение в свое приложение, которое можно перетаскивать из приложения. Как только рисунок выходит за пределы окна, должно открываться окно «Декодированный / прозрачный», в котором отображается только этот рисунок.

    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();

Событие DragDetected пока работает без проблем.

Проблема в том, что внутри события dragDone положение мыши всегда равно 0, и я не могу сказать, находится ли мышь внутри или вне моего приложения. Если мышь отпущена внутри приложения, ничего не должно произойти.

Я также попробовал с Robot Class, но я всегда получаю статичную странную позицию х / у.

Я использую JAVA 11 (принять JDK).

Спасибо за вашу помощь

3
Hauke 23 Авг 2019 в 22:41

2 ответа

Лучший ответ

У меня работает Robot (Oracle JDK 11 + JavaFX 12). Поскольку на самом деле вы не хотите перетаскивать какие-либо данные изображения, вы можете просто обойти эту проблему, немедленно создав новый этап и используя MOUSE_DRAGGED элемента ImageView, чтобы обновить положение окна:

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();
2
fabian 25 Авг 2019 в 09:41

Предлагаемое решение основано на ответе Фабиана.
Основное изменение заключено в методе withinBounds, который используется для определения, закончилось ли перетаскивание в границах окна. Этот метод основан на этом ответе:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.Window;

public class DragOut extends Application {

    @Override
    public void start(Stage primaryStage) {

        ImageView imageView = new ImageView("https://findicons.com/files/icons/345/summer/128/cake.png");
        StackPane stack = new StackPane(imageView);

        DragHandler dragHandler = new DragHandler();
        imageView.setOnDragDetected(event -> {
            Stage displayStage = makeNewStage(imageView.getImage());
            displayStage.setX(event.getScreenX());
            displayStage.setY(event.getScreenY());
            dragHandler.setStage(displayStage);
            displayStage.show();
            event.consume();
        });
        imageView.setOnMouseDragged(dragHandler);
        imageView.setOnMouseReleased(event -> {
            if (! withinBounds(event, imageView.getScene().getWindow()) && dragHandler.dragTarget != null) {
                // make stage fully opaque & cleanup
                dragHandler.showStage();
                imageView.setImage(null);
                event.consume();
            }else{
                dragHandler.closeStage();
            }
            dragHandler.setStage(null);
        });

        Scene scene = new Scene(stack, 300, 300);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private Stage makeNewStage(Image image) {

        Group root = new Group(new ImageView(image));
        root.setOpacity(0.5); // init stage at half transparency
        Stage displayStage = new Stage(StageStyle.TRANSPARENT);
        displayStage.setScene(new Scene(root, null));

        return displayStage;
    }

    private boolean withinBounds(MouseEvent event, Window window) {

        Point2D mouseLoc = new Point2D(event.getScreenX(), event.getScreenY());
        Rectangle2D windowBounds = new Rectangle2D(window.getX(), window.getY(),
                                            window.getWidth(), window.getHeight());
        return windowBounds.contains(mouseLoc);
    }

    class DragHandler implements EventHandler<MouseEvent> {

        private Stage dragTarget;

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

        void setStage(Stage stage){
            dragTarget = stage;
        }

        void showStage(){
            if (dragTarget != null) {
                dragTarget.getScene().getRoot().setOpacity(1);
            }
        }

        void closeStage(){
            if (dragTarget != null) {
                dragTarget.close();
            }
        }
    }

    public static void main(final String[] args) {
        launch(args);
    }
}
0
c0der 25 Авг 2019 в 07:25