【问题标题】:Why is drag and drop taking time on huge files?为什么拖放需要时间处理大文件?
【发布时间】:2021-09-17 13:26:32
【问题描述】:

我创建了一个 java 程序,它通过接受拖放的文件来工作。 每当我拖动小文件时,它都会起作用。但是当我在上面拖动 100MB 的大文件时,它会挂起,直到它完成处理文件。 我正在使用带有 macOS High Sierra 的 Macbook。

public ArrayList result() {

    TransferHandler th;
    th = new TransferHandler() {
        @Override
        public boolean canImport(JComponent comp, DataFlavor[] transfarFlavors) {
            return true;
        }

        @Override
        public boolean importData(JComponent comp, Transferable t) {

            try {
                List<File> files = (List<File>) t.getTransferData(DataFlavor.javaFileListFlavor);
                files.forEach((File file) -> {
                    String fName = file.getName();
                    String fPath = file.getAbsolutePath();
//I even added animation to show when the file is dropped, since small files are executed fast the animation doesn't show, but large files hang so no animation too.
                    ImageIcon loadPage = new ImageIcon(new ImageIcon("/Users/me/Pictures/hit.gif").getImage());
                    loadingImage.setIcon(loadPage);
                    Processor starts = new Processor();
                    try {
                        result = starts.getFile(fPath, fName);
                        setResult(result());

                        //fileNameText.setOpaque(true);
                    } catch (IOException ex) {
                        Logger.getLogger(DragnDrop.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(DragnDrop.class.getName()).log(Level.SEVERE, null, ex);
                    }
                });
            } catch (UnsupportedFlavorException | IOException ex) {
                Logger.getLogger(DragnDrop.class.getName()).log(Level.SEVERE, null, ex);
            }
            return true;
        }
    };
    DnD.setTransferHandler(th);

    return result;
}

【问题讨论】:

  • importData() 方法在 EDT 上运行,并在运行期间阻止所有 awt/swing 事件的处理。对于可以快速处理的小文件,这不是问题,但对于大文件,这是一个问题。你的importData() 方法应该只收集要处理的文件,然后启动一个后台线程来处理它们。
  • @Thomas Kläger 谢谢你的建议,我该怎么做?

标签: java macos file animation drag-and-drop


【解决方案1】:

要解决阻塞 EDT 的问题,您可以使用 javax.swing.SwingWorker

您的代码对于 Processor.getFile() 的结果是什么以及该结果会发生什么非常模糊,因此我只能对 SwingWorker 中的结果处理提出初步建议。

public ArrayList<Object> result() {

    TransferHandler th;
    th = new TransferHandler() {
        @Override
        public boolean canImport(JComponent comp, DataFlavor[] transfarFlavors) {
            return true;
        }

        @Override
        public boolean importData(JComponent comp, Transferable t) {

            try {
                ImageIcon loadPage = new ImageIcon(new ImageIcon("/Users/me/Pictures/hit.gif").getImage());
                loadingImage.setIcon(loadPage);
                List<File> files = (List<File>) t.getTransferData(DataFlavor.javaFileListFlavor);
                FileWorker fw = new FileWorker(files);
                fw.execute();
            } catch (UnsupportedFlavorException | IOException ex) {
                Logger.getLogger(DragnDrop.class.getName()).log(Level.SEVERE, null, ex);
            }
            return true;
        }
    };
    DnD.setTransferHandler(th);

    return null;
}

private static class FileWorker extends SwingWorker<Object, Object> {

    private final List<File> files;
    public FileWorker(List<File> files) {
        this.files = files;
    }

    @Override
    protected List<Object> doInBackground() throws Exception {
        List<Object> results = new ArrayList<>();
        files.forEach((File file) -> {
            String fName = file.getName();
            String fPath = file.getAbsolutePath();
            Processor starts = new Processor();
            try {
                Object result = starts.getFile(fPath, fName);
                results.add(result);
                publish(result);

            } catch (IOException | InterruptedException ex) {
                Logger.getLogger(DragnDrop.class.getName()).log(Level.SEVERE, null, ex);
            }
        });
        return results;
    }

    @Override
    protected void process(List<Object> chunks) {
        // here you could update UI elements with some intermediate results
    }

    @Override
    protected void done() {
        // here you could update UI elements with the final results
    }
}

【讨论】:

    猜你喜欢
    • 2017-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-12
    • 2019-03-16
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    相关资源
    最近更新 更多