Как использовать Drag-and-Drop в Swing для получения пути к файлу?

У меня есть JTextField в моем приложении swing, которое содержит путь к файлу файла, выбранного для использования. В настоящее время у меня есть JFileChooser, который используется для заполнения этого значения. Однако я хотел бы добавить возможность для пользователя перетаскивать файл на этот JTextField и помещать путь к файлу этого файла в JTextField, а не всегда использовать JFileChooser.

Как это может быть сделано?

Сначала вы должны посмотреть поддержку Swing DragDrop . После этого есть несколько небольших трюков для разных операционных систем. Как только у вас все получится, вы будете обрабатывать обратный вызов drop (). В этом обратном вызове вы захотите проверить DataFlavor Transferable.

Для Windows вы можете просто проверить DataFlavor.isFlavorJavaFileListType (), а затем получить свои данные следующим образом

List dropppedFiles = (List)transferable.getTransferData(DataFlavor.javaFileListFlavor) 

Для Linux (и, возможно, Solaris) DataFlavor немного сложнее. Вам нужно будет создать свой собственный DataFlavor, а тип Transferable будет отличаться

 nixFileDataFlavor = new DataFlavor("text/uri-list;class=java.lang.String"); String data = (String)transferable.getTransferData(nixFileDataFlavor); for(StringTokenizer st = new StringTokenizer(data, "\r\n"); st.hasMoreTokens();) { String token = st.nextToken().trim(); if(token.startsWith("#") || token.isEmpty()) { // comment line, by RFC 2483 continue; } try { File file = new File(new URI(token)) // store this somewhere } catch(...) { // do something good .... } } 

Существует примерная программа, которая содержит class, который можно использовать для облегчения перетаскивания файлов и папок:

http://www.iharder.net/current/java/filedrop/

Я тестировал это как с Windows 7, так и с Ubuntu 10.10, и, похоже, он хорошо работает в обеих средах.

Чтобы использовать его, вы добавляете что-то вроде этого в свой код:

  JPanel myPanel = new JPanel(); new FileDrop( myPanel, new FileDrop.Listener() { public void filesDropped( java.io.File[] files ) { // handle file drop ... } // end filesDropped }); // end FileDrop.Listener 

В случае, если вы не хотите тратить слишком много времени на изучение этого относительно сложного объекта, и вы работаете в Windows (или с использованием Java 7 или более поздней версии), вот краткий пример того, как принимать упавшие файлы с помощью JTextArea в качестве целевой цели :

 JTextArea myPanel = new JTextArea(); myPanel.setDropTarget(new DropTarget() { public synchronized void drop(DropTargetDropEvent evt) { try { evt.acceptDrop(DnDConstants.ACTION_COPY); List droppedFiles = (List) evt.getTransferable().getTransferData(DataFlavor.javaFileListFlavor); for (File file : droppedFiles) { // process files } } catch (Exception ex) { ex.printStackTrace(); } } }); 

Я знаю, что это старый вопрос, но текущие ответы немного устарели:

  • поскольку JDK 1.6 class ‘TransferHandler’ должен использоваться с новыми (перезаписанными) методами
  • поддержка Linux стала намного лучше, нет необходимости в пользовательской обработке

Это работает на Linux (KDE5) и Windows 7:

 final class FileDropHandler extends TransferHandler { @Override public boolean canImport(TransferHandler.TransferSupport support) { for (DataFlavor flavor : support.getDataFlavors()) { if (flavor.isFlavorJavaFileListType()) { return true; } } return false; } @Override @SuppressWarnings("unchecked") public boolean importData(TransferHandler.TransferSupport support) { if (!this.canImport(support)) return false; List files; try { files = (List) support.getTransferable() .getTransferData(DataFlavor.javaFileListFlavor); } catch (UnsupportedFlavorException | IOException ex) { // should never happen (or JDK is buggy) return false; } for (File file: files) { // do something... } return true; } } 

Используйте его на любом компоненте с помощью

 myComponent.setTransferHandler(new FileDropHandler()); 

Это работает для меня. Я использую его так (scala):

 def onDrop(files: List[java.io.File]): Unit = { ... } val lblDrop = new Label { peer.setTransferHandler(new FileDropHandler(onDrop)) border = EtchedBorder } class FileDropHandler(val onDrop: List[java.io.File] => Unit) extends javax.swing.TransferHandler { import javax.swing.JComponent import java.awt.datatransfer.{Transferable, DataFlavor} import java.net.URI import java.io.File val stdFileListFlavor = DataFlavor.javaFileListFlavor val nixFileListFlavor = new DataFlavor("text/uri-list;class=java.lang.String") override def canImport(comp: JComponent, flavors: Array[DataFlavor]): Boolean = flavors.exists(flavor => (flavor == stdFileListFlavor) || (flavor == nixFileListFlavor) ) override def importData(comp: JComponent, t: Transferable): Boolean = { val flavors = t.getTransferDataFlavors() val files = if (flavors.exists(_ == stdFileListFlavor)) { val data = t.getTransferData(stdFileListFlavor) importStdFileList( data ) } else if (flavors.exists(_ == nixFileListFlavor)) { val data = t.getTransferData(nixFileListFlavor) importNixFileList( data ) } else List() onDrop( files ) !files.isEmpty } private def importStdFileList(data: Any): List[File] = { data.asInstanceOf[List[File]] //XXX NOT TESTED } private def importNixFileList(data: Any): List[File] = { def clean(rawLine: String): Option[String] = { val line = rawLine.trim if (line.length == 0 || line == "#") None else Some(line) } def asURI(line: String): Option[URI] = { try { Some(new URI(line)) } catch { case e:Exception => println(e); None } } def asFile(uri: URI): Option[File] = { try { Some(new File(uri)) } catch { case e:Exception => println(e); None } } data.asInstanceOf[java.lang.String].split("\n") .toList flatMap clean flatMap asURI flatMap asFile } } 
  • KeyListener, keyPressed или keyTyped
  • Получить компонент Swing по имени
  • Слайд JPanel Содержимое в JForm на Java
  • Центр JDialog над родителем
  • Java - Как перетащить JPanel с его компонентами
  • Создание пользовательского JButton из изображений, содержащих прозрачные пиксели
  • Просмотрите файл изображения и покажите его с помощью Java Swing
  • Как узнать, когда пользователь действительно выпустил ключ на Java?
  • Откройте JPanel после нажатия кнопки в JFrame
  • Как настроить фокусировку на JTextField?
  • Java - проверьте, не является ли JTextField пустым или нет.
  • Давайте будем гением компьютера.