Frage

Ich habe eine JTextField in meinem Schwung-Anwendung, die den Dateipfad einer Datei verwendet werden soll, ausgewählt hält. Zur Zeit habe ich eine JFileChooser der verwendet wird, um diesen Wert zu füllen. Aber ich mag die Möglichkeit für einen Benutzer hinzufügen, um eine Datei auf diese JTextField Drag-and-Drop und hat es den Dateipfad der Datei in die JTextField platzieren, anstatt immer mit dem JFileChooser verwendet wird.

Wie kann dies geschehen?

War es hilfreich?

Lösung

Als erstes sollten Sie Drag & Drop-Unterstützung Schwingen . Danach gibt es nur wenige kleine Tricks für verschiedene Betriebssysteme. Sobald Sie die Dinge bekam gehen Sie das Drop () Callback werden handhaben. In diesem Rückruf sollten Sie die DataFlavor der übertragbaren überprüfen.

Für Windows können Sie einfach überprüfen Sie die DataFlavor.isFlavorJavaFileListType () und dann Daten wie diese erhalten

List<File> dropppedFiles = (List<File>)transferable.getTransferData(DataFlavor.javaFileListFlavor)

Für Linux (und wahrscheinlich Solaris) die DataFlavor ist ein wenig komplizierter. Sie benötigen, um Ihre eigenen DataFlavor und der übertragbaren Typ unterschiedlich sein wird machen

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
       ....
    }
}

Andere Tipps

Es ist ein Beispielprogramm, die eine Klasse enthält, die zur Erleichterung des Drag verwendet werden können, und für Dateien und Ordner löschen:

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

Getestet habe ich diese mit Windows 7 und Ubuntu 10.10, und es scheint, in beiden Umgebungen gut zu funktionieren.

Um es nutzen zu können, um so etwas zu Ihrem Code hinzu:

  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

Falls Sie wollen nicht zu viel Zeit damit verbringen, diesen relativ komplexes Thema forscht, und Sie sind auf Windows (oder mit Hilfe von Java 7 oder höher), hier ein kurzes Beispiel, wie abgelegten Dateien mit einem JTextArea zu akzeptieren, wie ein Drop-Ziel:

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

Ich weiß, das ist eine alte Frage, aber die aktuellen Antworten sind alle ein bisschen veraltet:

  • seit JDK 1.6 die Klasse 'TransferHandler' mit neuen (überschrieben) Methoden verwendet werden soll
  • Unterstützung für Linux wurde viel besser, keine Notwendigkeit für individuelle Handhabung

Dies funktioniert unter Linux (KDE5) und 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<File> files;
        try {
            files = (List<File>) 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;
    }
}

Verwenden Sie es auf jede Komponente mit

myComponent.setTransferHandler(new FileDropHandler());

Das funktioniert für mich. Ich benutze es so (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
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top