JavaFX:拖放操作导致冻结放置图标后弹出警报

JavaFX: Alert popup after drag-and-drop action casues frozen drop icon

使用 JavaFX 8 我遇到了一个特定的拖放问题:

拖放后的确认弹出窗口会在释放拖动时将图标卡在屏幕上,甚至会覆盖警告对话框本身,如下所示:


(来源:image.ibb.co

文本“复制”和图标会一直卡住,直到用户关闭弹出窗口。

这是重现问题的最少代码。要测试,运行 这个程序并将任何文件(例如从桌面)拖到应用程序 window:

public class Main extends Application {

private Parent root = new VBox();

private void onDragOver(DragEvent dragEvent) {
    if (dragEvent.getDragboard().hasFiles()) {
        dragEvent.acceptTransferModes(TransferMode.COPY);
    }
}

private void isUserSure() {
    Alert alert = new Alert(Alert.AlertType.WARNING,"",ButtonType.OK);
    alert.showAndWait();
}

@Override
public void start(Stage primaryStage) {
    root.setOnDragOver((event) -> onDragOver(event));
    root.setOnDragDropped((event) -> isUserSure());
    primaryStage.setTitle("ghost demo");
    primaryStage.setScene(new Scene(root, 300, 275));
    primaryStage.show();
}

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

我通过执行以下操作自行解决了该问题:

知道模式对话框(警告弹出窗口等)基本上 "block" 每隔一个阶段通过调用 showAndwait() 问题一定是这也阻止了 dragEvent 完成onDragDropped 方法(通过 setOnDragDropped 中的 lambda 设置)。

确保将对弹出方法的调用包装起来,并将发生在 Platform.runLater()

中的实际掉落物品的内容

这会让 dragEvent 的东西先完成。观察我在以下方法行中所做的更改 start:

root.setOnDragDropped((event) -> Platform.runLater(() -> isUserSure()));

请确保不要包装多余的东西,否则 Dragboard 中的项目将超出范围。从 Dragboard 中提取所需的物品必须在掉落时发生,而不是在 runLater()

要使其正常工作,runLater 必须从辅助线程启动:

root.setOnDragDropped((event) -> {
 Thread t = new Thread(() -> {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException interruptedException) {
                    interruptedException.printStackTrace();
                }
                Platform.runLater(() ->Platform.runLater(() -> isUserSure(););
            });
            t.run();
);