1

所以我实现了一个非常简单的拖放文件上传小部件。基本上我的小部件是一个垂直面板,里面有几个标签和一个按钮。用户可以将文件拖入垂直面板或单击按钮并浏览文件。

我的问题是,当我将文件拖到垂直面板中时,每次我将项目拖到标签或按钮占用的空间上时,它都会触发 DragLeaveEvent。我希望它知道该项目位于垂直面板中,即使它位于标签或按钮的顶部。我确定我错过了一些简单的东西。我通过将这些 dom 处理程序添加到垂直面板来提供拖动功能:

addDomHandler(new DragEnterHandler() {
            @Override
            public void onDragEnter(DragEnterEvent event) {
                System.out.println("drag enter");
                highlight(true);
            }
        }, DragEnterEvent.getType());

addDomHandler(new DragLeaveHandler() {
            @Override
            public void onDragLeave(DragLeaveEvent event) {
                System.out.println("drag leave");
                highlight(false);
            }
        }, DragLeaveEvent.getType());

addDomHandler(new DragOverHandler() {
            @Override
            public void onDragOver(DragOverEvent event) {
            }
        }, DragOverEvent.getType());

addDomHandler(new DropHandler() {
            @Override
            public void onDrop(DropEvent event) {
                System.out.println("drop");
                // stop default behaviour
                event.preventDefault();
                event.stopPropagation();

                // starts the fetching, reading and callbacks
                if (fileUploadHandler != null) {
                    handleFiles(event.getDataTransfer(), fileUploadHandler);
                }
                highlight(false);
            }
        }, DropEvent.getType());    
4

3 回答 3

0

通过大量研究,我得出了我能找到的唯一解决方案。我在 dragover 处理程序中将 highlight 设置为 true 而不是拖动 enter。

    panel.addDomHandler(new DragEnterHandler() {
        @Override
        public void onDragEnter(DragEnterEvent event) {
        }
    }, DragEnterEvent.getType());

    panel.addDomHandler(new DragLeaveHandler() {
        @Override
        public void onDragLeave(DragLeaveEvent event) {
            highlight(false);
        }
    }, DragLeaveEvent.getType());

    panel.addDomHandler(new DragOverHandler() {
        @Override
        public void onDragOver(DragOverEvent event) {
            highlight(true);
        }
    }, DragOverEvent.getType());

    panel.addDomHandler(new DropHandler() {
        @Override
        public void onDrop(DropEvent event) {
            // stop default behaviour
            event.preventDefault();
            event.stopPropagation();

            // starts the fetching, reading and callbacks
            handleFiles(event.getDataTransfer());
            highlight(false);
        }
    }, DropEvent.getType());
于 2013-07-22T14:53:58.857 回答
0

检查事件目标是否是面板的子(或孙子),或者在这种情况下,可能更确切地说事件目标是否正是面板的元素:

if (verticalPanel.getElement().isOrHasChild(Node.as(event.getNativeEvent().getEventTarget()))) {
   // within the panel (possibly on a child)
}

if (verticalPanel.getElement() == Node.as(event.getNativeEvent().getEventTarget())) {
   // targetting exactly the panel (e.g. leaving the panel, not one of its children)
}
于 2013-07-18T16:13:24.393 回答
0

我复制粘贴了您的代码,还添加了一个:

RootPanel.get().addHandler(dropHandler, DropEvent.getType());

我的 drophandler 看起来像这样:

DropHandler dropHandler = new DropHandler() {

        @Override
        public void onDrop(DropEvent event) {
            handleFiles(event.getDataTransfer(), new FileUploadHandler() {
                @Override
                public TYPE specifyFileType() {
                    return TYPE.BINARY;
                }

                @Override
                public void handleFileContent(String fileName, String fileContent) {
                    // do stuff with filename and content
                }

                @Override
                public boolean checkFileName(String fileName) {
                    return true;
                }
            });
            event.preventDefault();
            event.stopPropagation();
        }
    };

和文件上传接口:

public interface FileUploadHandler {

    static public enum TYPE {
         TEXT, BINARY, DATAURL
    };

    // check the filename and extension and return true if you are happy with
    // proceeding
    // returnning false will prevent the file from being read
    boolean checkFileName(String fileName);

    // tell the method to use to read this file
    TYPE specifyFileType();

    // do your stuff here, eg upload to a server
    void handleFileContent(String fileName, String fileContent);
}

和句柄文件功能:(请注意,您必须将类路径更改为 FileUploadHandler 接口)

// native method to make use of the HTML5 file API functionality
private final native void handleFiles(JavaScriptObject dataTransfer, FileUploadHandler fileUploadHandler) /*-{
    var files = dataTransfer.files;
    var i;
    var file;
    var reader = new FileReader();
    for (i = 0; i < files.length; i++) {
        file = files[i];
        if (fileUploadHandler.@<classpath_to>.FileUploadHandler::checkFileName(Ljava/lang/String;)(file.name)) {
            var type = fileUploadHandler.@<classpath_to>.FileUploadHandler::specifyFileType()();
            reader.onload = function(e) {
                fileUploadHandler.@<classpath_to>.FileUploadHandler::handleFileContent(Ljava/lang/String;Ljava/lang/String;)(file.name, e.target.result);
            }
            if (type == "TEXT") {
                reader.readAsText(file);
            } else if (type == "BINARY") {
                reader.readAsBinaryString(file);
            } else if (type == "DATAURL") {
                reader.readAsDataURL(file);
                // not supported
            } else if (type == "ARRAYBUFFER") {
                reader.readAsArrayBuffer(file);
            } else {
            }
        }
    }
}-*/;
于 2019-08-28T14:50:28.830 回答