【问题标题】:Drag and Drop Java with Swing Worker使用 Swing Worker 拖放 Java
【发布时间】:2013-07-19 18:10:21
【问题描述】:

我想创建一个从 JList 到操作系统的 DND 操作。我现在的解决方案是使用 TransferHandler。在 createTransferable 方法中,我使用要复制的文件创建 Transferable。
但是现在我的问题出现了:在某些情况下,我必须先从 FTP 服务器下载文件,然后才能复制文件。非常繁重的下载操作在 JavaSwingWorker 中运行(隐藏在 d.download(tmpDir); 语句后面)。现在系统尝试复制尚未下载的文件。

现在我需要一种机制,允许我在下载文件后创建可传输的。我的问题有解决方案吗?请帮帮我!

谢谢!

这是我的方法:

public Transferable createTransferable(JComponent c) {
    JList list = (JList) c; // we know it's a JList
    List<PictureDecorator> selectedPictures = getSelectedValues(list.getModel());
    Vector cpFiles = new Vector();

    List<Picture> donePictures = new ArrayList<Picture>();
    List<Picture> notDonePictures = new ArrayList<Picture>();
    String tmpDir = System.getProperty("java.io.tmpdir");

    for(PictureDecorator pd : selectedPictures){
        if(pd.getPic().getStatus() == PictureStatus.DONE)
            donePictures.add(pd.getPic());
        else
            notDonePictures.add(pd.getPic());
    }

    Downloader d = new Downloader(parent, loginInformation, sced, donePictures, order);

    d.download(tmpDir);

    for(Picture p : donePictures){
        cpFiles.add(new File(tmpDir + File.separator + p.getPicture().getName()));
    }

    for(Picture p : notDonePictures) {
        cpFiles.add(p.getPicture());
    }

    TransferableFile tf = new TransferableFile(cpFiles);
    return tf;
}

我需要启动拖动过程的东西,然后我得到拖动的路径,然后我可以下载图片并将其复制到目标路径。

编辑:或者另一种表述:当我进入操作系统时,如何找到放置目的地?

【问题讨论】:

  • 不清楚您要做什么。为什么要在 DnD 期间执行如此繁重的操作?您只需要传输下载内容的信息,即文件名的一组字符串。下载结束后,确定文件是什么,然后开始下载
  • 感谢您的回答,但我正在尝试将文件放到操作系统而不是我的程序的另一个控件!如何确定用户将文件放在哪里?
  • 我很抱歉。我完全错过了操作系统部分。虽然我不确定这是否是等待任务完成的方法,例如while ( !d.isDone() ) { Thread.sleep(...) }?

标签: java drag-and-drop operating-system


【解决方案1】:

要开始拖动,您需要JList 上的TransferHandlerDragSourceDragGestureListener 的组合。您可以在下面看到使用JTextField 执行此操作的示例:

final JTextField textField = new JTextField(50);
DragGestureListener dragListener = new DragGestureListener() {
    @Override
    public void dragGestureRecognized(DragGestureEvent dge) {
        // how the drag cursor should look like
        Cursor cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);

        // the component being dragged
        JTextField tf = (JTextField) dge.getComponent();

        // Here a Transferable is created directly for a single file name
        dge.startDrag(cursor, new TransferableFile(tf.getText()));
    }
};

final DragSource ds = new DragSource();
ds.createDefaultDragGestureRecognizer(textField, DnDConstants.ACTION_COPY, dragListener);

您可以将上述代码放入您的窗口创建过程中。

您生成的可转让(在您的情况下为TransferableFile)应该支持DataFlavor.javaFileListFlavor,并且您应该从getTransferData(DataFlavor flavor) 方法返回Files 的List

我相信这也是应该进行下载的方法,因为这是在 JVM-OS 接管之前您可以控制的最后一点。

现在关于SwingWorker 问题,您可以在方法内部等待,直到下载完成。也许修改您的 Downloader 类以公开一个布尔标志,这样您就可以执行类似 while (!downloader.isDone()) { Thread.sleep(millisToSleep) }; 的操作

[编辑:我必须承认我不喜欢让 EventDispath 线程保持忙碌的想法,但如果这解决了您当前的问题,也许您可​​以稍后研究更优雅的解决方案]

一点警告:由于您无权访问放置位置,因此您无法知道getTransferData 将被调用多少次。最好考虑到这一点,并使用您目前下载的临时文件创建一个简单的缓存(Map 听起来很合理)。如果您在缓存中找到该文件,则直接返回其对应的临时文件,不要再次下载。

希望有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    相关资源
    最近更新 更多