2

JList コンポーネントのドラッグ アンド ドロップのサポートに取り組んでおり、ファイル ブラウザからドラッグしたファイルをサポートできるようにしたいと考えています。ただし、フォルダーではなくファイルのドラッグのみを許可したいので、次のように TransferHandler で確認しようとしています。

@Override
public boolean canImport(TransferSupport support) {

    if (support.getComponent().equals(this.resourceFileList)) {

        if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
            return false;
        } else {

            try {

                // get file list
                Transferable transferable = support.getTransferable();
                Object transferData = transferable.getTransferData(DataFlavor.javaFileListFlavor);

                // check for folders
                boolean containsFiles = false;
                List files = (List) transferData;
                for (int i = 0; i < files.size(); i++) {
                    File file = (File) files.get(i);
                    if (!file.isDirectory()) {
                        containsFiles = true;
                    }
                }

                // return file indicator
                return containsFiles;

            } catch (IOException | UnsupportedFlavorException e) {
                System.out.println("Unable to check for folders due to the following exception:\n" + e);
                return false;
            }
        }
    } else {
        return false;
    }
}

残念ながら、ここではtransferDataが null のようです。ただし、 TransferHandlerimportDataメソッドが呼び出されるときではありません。これが何らかのバグであるか、または望ましい動作であるかどうか、誰にも手掛かりがありますか?

違いがあり、Javaバージョンが1.7.0_21の場合、私はMac(OSX 10.8)を使用しています。

前もって感謝します!

編集:

これは、誰でもテストできる短い SSCCE です。ファイルをリストにドラッグするだけで、コンソールを確認できます。

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;

import java.io.File;
import java.io.IOException;

import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.TransferHandler;
import javax.swing.TransferHandler.TransferSupport;

public class DNDIssue extends TransferHandler {

    @Override
    public boolean canImport(TransferSupport support) {

        if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {

            try {

                Transferable transferable = support.getTransferable();
                Object transferData = transferable.getTransferData(DataFlavor.javaFileListFlavor); // <-- this returns null
                System.out.println(transferData); // null

            } catch (IOException | UnsupportedFlavorException e) {
                System.out.println("Unable to check for folders due to the following exception:\n" + e);
            } finally {
                return false;
            }
        } else {
            return false;
        }
    }

    public static void main(String[] args) {

        // create window
        JFrame window = new JFrame("DNDIssue");
        window.setSize(640, 480);
        window.setLocation(100, 100);

        // create list with model and set transfer handler
        JList<File> list = new JList<File>(new DefaultListModel<File>());
        list.setTransferHandler(new DNDIssue());

        // add enclosing scroll pane and display window
        window.getContentPane().add(new JScrollPane(list));
        window.setVisible(true);
    }
}
4

1 に答える 1

2
  • あなたの SSCCE は、Windows 7 64 ビットで JDK 1.7.0_21 を使用して問題なく動作します。
  • 次のコードを試していただけますか?

    Transferable transferable = support.getTransferable();
    
    System.out.println("----");
    String mt = DataFlavor.javaFileListFlavor.getMimeType();
    for(DataFlavor df: transferable.getTransferDataFlavors()) {
      System.out.println(df.getMimeType());
      System.out.println("  "+df.getMimeType().equals(mt));
    }
    
  • SSCCE 1.0: 削除

  • SSCCE 1.1:TransferHandler#importData(...)バージョンのオーバーライド

  • SSCCE 1.2: 無視InvalidDnDOperationException

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.io.*;
import java.util.List;
import javax.swing.*;
import javax.swing.TransferHandler;
import javax.swing.TransferHandler.TransferSupport;

public class DNDIssueTest {
  public JComponent makeUI() {
    // create list with model and set transfer handler
    JList<File> list = new JList<File>(new DefaultListModel<File>());
    list.setDropMode(DropMode.INSERT);
    list.setTransferHandler(new FileTransferHandler());
    return new JScrollPane(list);
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new DNDIssueTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

class FileTransferHandler extends TransferHandler {
  private static final boolean DEBUG = true;
  @SuppressWarnings("unchecked")
  @Override public boolean importData(TransferSupport support) {
    try {
      List files = (List)support.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
      System.out.println("importData");
      if(!hasDirectory(files) && canImport(support)) {
        JList list = (JList)support.getComponent();
        DefaultListModel model = (DefaultListModel)list.getModel();
        for(Object o: files) {
          model.addElement(o);
        }
        return true;
      }
    } catch(Exception ex) {
      ex.printStackTrace();
    }
    return false;
  }
  private boolean hasDirectory(List list) {
    System.out.println("hasDirectory check");
    for (Object o: list) {
      if(o instanceof File) {
        File file = (File) o;
        if (file.isDirectory()) {
          return true;
        }
      }
    }
    return false;
  }
  @Override public boolean canImport(TransferSupport support) {
    if(!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
      return false;
    }
    if(!DEBUG) return true;

    Transferable transferable = support.getTransferable();
    try {
      Object transferData = transferable.getTransferData(DataFlavor.javaFileListFlavor);
      //System.out.println(transferData); // null
      System.out.println("canImport");
      return !hasDirectory((List)transferData);
    } catch (Exception e) {
      //e.printStackTrace();
      System.out.println("*** Ignore InvalidDnDOperationException ***");
      return true;
    }
  }
}
  • SSCCE 2.0:DropTargetListenerバージョン
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.io.*;
import java.util.List;
import javax.swing.*;

public class DNDIssueTest2 {
  public JComponent makeUI() {
    final DefaultListModel<File> model = new DefaultListModel<>();
    JList<File> list = new JList<File>(model);
    DropTargetListener dtl = new DropTargetAdapter() {
      @Override public void dragOver(DropTargetDragEvent dtde) {
        if(dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
          Transferable transferable = dtde.getTransferable();
          Object transferData = null;
          try {
            transferData = transferable.getTransferData(DataFlavor.javaFileListFlavor);
          } catch(Exception ex) {
            dtde.rejectDrag();
            return;
          }
          List<File> files = (List<File>)transferData;
          for (int i = 0; i < files.size(); i++) {
            File file = (File) files.get(i);
            if (file.isDirectory()) {
              dtde.rejectDrag();
              return;
            }
          }
          dtde.acceptDrag(DnDConstants.ACTION_COPY);
          return;
        }
        dtde.rejectDrag();
      }
      @Override public void drop(DropTargetDropEvent dtde) {
        try {
          if(dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
            dtde.acceptDrop(DnDConstants.ACTION_COPY);
            Transferable transferable = dtde.getTransferable();
            List list = (List)transferable.getTransferData(DataFlavor.javaFileListFlavor);
            for(Object o: list) {
              if(o instanceof File) {
                File file = (File) o;
                model.addElement(file);
              }
            }
            dtde.dropComplete(true);
            return;
          }
        } catch(UnsupportedFlavorException ufe) {
          ufe.printStackTrace();
        } catch(IOException ioe) {
          ioe.printStackTrace();
        }
        dtde.rejectDrop();
      }
    };
    new DropTarget(list, DnDConstants.ACTION_COPY, dtl, true);
    return new JScrollPane(list);
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new DNDIssueTest2().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}
于 2013-05-17T10:27:14.890 に答える