使用Swing Worker拖放Java

使用Swing Worker拖放Java,java,drag-and-drop,operating-system,Java,Drag And Drop,Operating System,我想创建一个从JList到操作系统的DND操作。我现在的解决方案是使用TransferHandler。在createTransferable方法中,我使用要复制的文件创建Transferable但现在我的问题是:在某些情况下,我必须先从FTP服务器下载文件,然后才能复制文件。非常繁重的下载操作在JavaSwingWorker中运行(隐藏在语句d.download(tmpDir);后面)。现在,系统尝试复制尚未下载的文件 现在我需要一种机制,允许我在下载文件后创建可转移文件。我的问题有解决办法吗?

我想创建一个从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;
}
public可转让组件(JComponent c){
JList=(JList)c;//我们知道它是一个JList
List selectedPictures=getSelectedValues(List.getModel());
向量cpFiles=新向量();
List donePictures=new ArrayList();
List notDonePictures=new ArrayList();
字符串tmpDir=System.getProperty(“java.io.tmpDir”);
用于(PicturedCorator pd:selectedPictures){
if(pd.getPic().getStatus()==PictureStatus.DONE)
添加(pd.getPic());
其他的
notdoneipictures.add(pd.getPic());
}
Downloader d=新的Downloader(父级、登录信息、sced、donePictures、订单);
d、 下载(tmpDir);
用于(图p:donePictures){
添加(新文件(tmpDir+File.separator+p.getPicture().getName());
}
用于(图p:notDonePictures){
添加(p.getPicture());
}
TransferableFile tf=新的TransferableFile(cpFiles);
返回tf;
}
我需要启动拖动程序的东西,然后我得到拖动的路径,然后我可以下载图片并将其复制到目标路径


编辑:或另一个公式:当我放入操作系统时,如何找到拖放目的地?

要开始拖动,您需要
JList
上的
TransferHandler
,或者
DragSource
DragGestureListener
组合使用。下面您可以看到一个使用
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.javafilelistfravor
,并且应该从
getTransferData(DataFlavor)
方法返回
文件的
列表

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

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

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

有一点警告:由于您无权访问放置位置,因此无法知道调用
getTransferData
的次数。最好考虑到这一点,并使用迄今为止下载的临时文件创建一个简单的缓存(映射听起来很合理)。如果在缓存中找到该文件,则直接返回其相应的临时文件,不再下载


希望这有帮助

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