简体   繁体   English

JavaFx Webview HTML5 DragAndDrop

[英]JavaFx Webview HTML5 DragAndDrop

From this code : http://docs.oracle.com/javafx/2/swing/SimpleSwingBrowser.java.htm 从以下代码: http//docs.oracle.com/javafx/2/swing/SimpleSwingBrowser.java.htm

I'm loading this html page : 我正在加载这个html页面:

<!DOCTYPE HTML>
<html>
<head>
<title>HTML5 AJAX Uploader</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<script type="text/javascript">
    function allowDrop(ev) {
        ev.preventDefault();
    }
    function drop(ev) {
        ev.preventDefault();
        console.log(JSON.stringify(ev.dataTransfer));
    }
</script>
</head>
<body>
<div id="droparea"
     style="border: 1px solid #000000; width: 100px; height: 100px;"
     ondrop="drop(event)"
     ondragover="allowDrop(event)">drop area</div> 
</body>

Normaly, I should have in the "drop" function the json object "ev.dataTransfer" with "files" property not null as it happens with normal webkit browser then do the upload (not present here). Normaly,我应该在“drop”函数中将json对象“ev.dataTransfer”与“files”属性不为null,因为它发生在普通的webkit浏览器然后进行上传(此处不存在)。

Should I implement something more in Java ? 我应该在Java中实现更多功能吗? ;(

All kinds of help will be appreciated :) thanks 各种帮助将不胜感激:)谢谢

This doesn't work out of the box, see here: https://bugs.openjdk.java.net/browse/JDK-8096939 这不是开箱即用的,请看这里: https//bugs.openjdk.java.net/browse/JDK-8096939

You must handle the events on the Webview and reinject them into the browser component (WebEngine). 您必须处理Webview上的事件并将它们重新注入浏览器组件(WebEngine)。 Below is an example. 以下是一个例子。 I'm using this with with Angular2 and the ng2-file-upload plugin ( https://github.com/valor-software/ng2-file-upload ). 我正在使用Angular2和ng2-file-upload插件( https://github.com/valor-software/ng2-file-upload )。

Use new WebViewWithFileDragEvents(webView) to install the events in your WebView . 使用new WebViewWithFileDragEvents(webView)WebView安装事件。 It is not pretty but works for me. 它不漂亮,但适合我。

import static java.lang.String.format;

import java.io.File;
import java.util.Arrays;
import java.util.stream.Collectors;

import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.web.WebView;

public class WebViewWithFileDragEvents {
    private final WebView webview;

    public WebViewWithFileDragEvents(WebView webview) {
        this.webview = webview;
        this.webview.getEngine().setJavaScriptEnabled(true);
        this.webview.setOnDragOver(this::handleOnDragOver);
        this.webview.setOnDragDropped(this::handleOnDragDropped);
    }

    private void handleOnDragOver(DragEvent e) {
        Dragboard db = e.getDragboard();
        if (db.hasFiles()) {
            e.acceptTransferModes(TransferMode.COPY);
            injectDragOverEvent(e);
        } else {
            e.consume();
        }
    }

    private void injectDragOverEvent(DragEvent e) {
        inject(join("",
                "{",
                "  var newElement=document.elementFromPoint(%d,%d);",
                "  if (window.lastInjectedEvent && window.lastInjectedEvent != newElement) {",
                "     //fire dragout",
                "     window.lastInjectedEvent.dispatchEvent(%s)",
                "  }",
                "  window.lastInjectedEvent = newElement",
                "  newElement.dispatchEvent(%s);",
                "}"),
                (int) e.getX(), (int) e.getY(), dragLeaveEvent(e), dragOverEvent(e));
    }

    private String join(String... lines) {
        return String.join("\n", Arrays.asList(lines));
    }

    private void inject(String text, Object... args) {
        webview.getEngine().executeScript(String.format(text, args));
    }

    private String dragLeaveEvent(DragEvent e) {
        return join("",
                "function() {",
                "  var e = new Event('dragleave');",
                "  e.dataTransfer={ types: ['Files']};",
                "  return e;",
                "}()");
    }

    private String dragOverEvent(DragEvent e) {
        return join("",
                "function() {",
                "  var e = new Event('dragover');",
                "  e.dataTransfer={ types: ['Files']};",
                "  return e;",
                "}()");
    }

    private String dropEvent(DragEvent e) {
        String files = e.getDragboard().getFiles()
                .stream()
                .map(File::getAbsolutePath)
                .map(f -> "{ name: '" + f + "'}")
                .collect(Collectors.joining(",", "[", "]"));

        return format(join("",
                "function() {",
                "  var e = new Event('drop');",
                " e.dataTransfer={ files: %s};",
                "  return e;",
                "}()"),
                files);

    }

    private void handleOnDragDropped(DragEvent e) {
        boolean success = false;
        if (e.getDragboard().hasFiles()) {
            success = true;
            injectDropEvent(e);
        }
        e.setDropCompleted(success);
        e.consume();
    }

    private void injectDropEvent(DragEvent e) {
        inject(join("",
                "{",
                "  var newElement=document.elementFromPoint(%d,%d);",
                "  newElement.dispatchEvent(%s);",
                "}"),
                (int) e.getX(), (int) e.getY(), dropEvent(e));

    }
}

I have had some problems using the javafx browser example myself. 我自己使用javafx浏览器示例时遇到了一些问题。 In the end, I used the eclipse swt browser widget in the programs I needed this functionality. 最后,我在我需要此功能的程序中使用了eclipse swt浏览器小部件。 Perhaps it's worth a look. 也许值得一看。

http://www.eclipse.org/articles/Article-SWT-browser-widget/browser.html http://www.eclipse.org/articles/Article-SWT-browser-widget/browser.html

Edit: Just to add some info, this browser widget has the option of being webkit based, while still offering the ability to interact with it the way you would with javafx. 编辑:只是为了添加一些信息,这个浏览器小部件可以选择基于webkit,同时仍然提供与javafx一样的交互方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM