JavaFx Webview HTML5 DragAndDrop

1

Из этого кода: http://docs.oracle.com/javafx/2/swing/SimpleSwingBrowser.java.htm

Я загружаю эту страницу 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>

Нормальный, я должен иметь в функции "drop" объект json "ev.dataTransfer" с свойством "files", который не имеет значения null, как это происходит с обычным браузером webkit, а затем выполняет загрузку (здесь нет).

Должен ли я реализовать что-то еще на Java? ; (

Все виды помощи будут оценены :) спасибо

Теги:
javafx
swing
webview

2 ответа

3

Это не работает из коробки, см. Здесь: https://bugs.openjdk.java.net/browse/JDK-8096939

Вы должны обрабатывать события в Webview и повторно вводить их в компонент браузера (WebEngine). Ниже приведен пример. Я использую это с помощью Angular2 и плагина ng2-file-upload (https://github.com/valor-software/ng2-file-upload).

Используйте new WebViewWithFileDragEvents(webView) для установки событий в вашем WebView. Это не очень, но работает для меня.

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

    }
}
  • 0
    Однако, после введения событий, как мы на самом деле обрабатываем их в веб-просмотре? события не запускаются, когда у меня есть слушатели на элементах dropzone
  • 0
    Приведенный выше код эмулирует поведение, как в обычном браузере, но для веб-просмотра JavaFX. В основном это берет события JavaFX и запускает их на элементе под указателем мыши в веб-представлении. Вы пробовали свой код JS / HTML, например, в Chrome, и проверяли, получаете ли вы события в своем коде JS? Если это не работает, вы должны исправить это в первую очередь.
Показать ещё 5 комментариев
0

У меня были некоторые проблемы с использованием примера браузера javafx. В конце концов, я использовал виджет браузера eclipse swt в тех программах, которые мне нужны для этой функции. Возможно, стоит посмотреть.

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

Изменить. Чтобы добавить некоторую информацию, этот виджет браузера имеет возможность быть основанным на веб-китах, но при этом предлагает возможность взаимодействовать с ним так, как вы бы с javafx.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню