web-dev-qa-db-fra.com

Comment puis-je utiliser le glisser-déposer dans Swing pour obtenir le chemin du fichier?

J'ai un JTextField dans mon application swing qui contient le chemin d'accès d'un fichier sélectionné pour être utilisé. Actuellement, j'ai un JFileChooser qui est utilisé pour remplir cette valeur. Cependant, je voudrais ajouter la possibilité pour un utilisateur de glisser-déposer un fichier sur ce JTextField et de lui faire placer le chemin d'accès de ce fichier dans le JTextField au lieu de toujours utiliser le JFileChooser.

Comment cela peut-il être fait?

38
Ascalonian

Vous devez d'abord examiner Prise en charge de Swing DragDrop . Après cela, il y a quelques petites astuces pour différents systèmes d'exploitation. Une fois que vous avez commencé, vous allez gérer le rappel drop (). Dans ce rappel, vous voudrez vérifier la DataFlavor du transférable.

Pour Windows, vous pouvez simplement vérifier le DataFlavor.isFlavorJavaFileListType () puis obtenir vos données comme ceci

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

Pour Linux (et probablement Solaris), DataFlavor est un peu plus délicat. Vous devrez créer votre propre DataFlavor et le type transférable sera différent

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

Il existe un exemple de programme qui contient une classe qui peut être utilisée pour faciliter le glisser-déposer des fichiers et des dossiers:

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

J'ai testé cela avec Windows 7 et Ubuntu 10.10, et cela semble bien fonctionner dans les deux environnements.

Pour l'utiliser, vous ajoutez quelque chose comme ça à votre code:

  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
33
Mr Ed

Si vous ne voulez pas passer trop de temps à rechercher ce sujet relativement complexe et que vous utilisez Windows (ou utilisez Java 7 ou version ultérieure), voici un exemple rapide sur la façon d'accepter fichiers déposés avec un JTextArea comme cible de dépôt:

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();
        }
    }
});
28
rustyx

Je sais que c'est une vieille question mais les réponses actuelles sont toutes un peu dépassées:

  • depuis JDK 1.6, la classe 'TransferHandler' devrait être utilisée avec de nouvelles méthodes (écrasées)
  • la prise en charge de Linux est devenue beaucoup mieux, pas besoin de gestion personnalisée

Cela fonctionne sous Linux (KDE5) et 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;
    }
}

Utilisez-le sur n'importe quel composant avec

myComponent.setTransferHandler(new FileDropHandler());
15
ABika