كيف يمكنني استخدام السحب والإفلات في البديل للحصول على مسار الملف?

StackOverflow https://stackoverflow.com/questions/811248

  •  03-07-2019
  •  | 
  •  

سؤال

لدي JTextField في تطبيق البديل الذي يحمل ملف مسار الملف المحدد إلى استخدامها.حاليا لدي JFileChooser المستخدمة في تعبئة هذه القيمة.ولكن أود أن أضيف قدرة المستخدم قم بسحب وإسقاط ملف على هذا JTextField ويكون ذلك وضع مسار الملف هذا الملف في JTextField بدلا من استخدام JFileChooser.

كيف يمكن القيام بذلك ؟

هل كانت مفيدة؟

المحلول

أولا يجب أن ننظر إلى سوينغ الدعم DragDrop . بعد ذلك هناك عدد قليل من الحيل قليلا لأنظمة التشغيل المختلفة. مرة واحدة كنت قد حصلت على الأمور تسير فسوف يكون التعامل مع رد قطرة (). في هذا الاستدعاء فأنت تريد أن تحقق من DataFlavor للتحويل.

لويندوز يمكنك التحقق فقط في DataFlavor.isFlavorJavaFileListType () ومن ثم الحصول على البيانات الخاصة بك مثل هذا

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

لينكس (وربما سولاريس) وDataFlavor هو اصعب قليلا. سوف تحتاج إلى إجراء DataFlavor الخاصة بك وسوف نوع للتحويل تكون مختلفة

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

نصائح أخرى

وهناك البرنامج المثال الذي يحتوي على فئة التي يمكن استخدامها لتسهيل سحب وإسقاط الملفات والمجلدات:

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

وأنا جربت هذا مع كل من ويندوز 7 وأوبونتو 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

في حال كنت لا تريد أن تنفق الكثير من الوقت في البحث عن هذا الموضوع المعقد نسبيا، وكنت على ويندوز (أو باستخدام جافا 7 أو في وقت لاحق)، وهنا مثال سريع على كيفية قبول إسقاط الملفات مع JTextArea كما انخفاض الهدف:

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

أعرف أن هذا هو السؤال القديم ولكن الإجابات كلها عفا عليها الزمن قليلا:

  • منذ JDK 1.6 فئة 'TransferHandler' ينبغي أن تستخدم مع (الكتابة) أساليب
  • دعم لينكس أصبحت أفضل كثيرا ، لا حاجة مخصص التعامل مع

وهذا يعمل على لينكس (KDE5) ويندوز 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;
    }
}

استخدامه على أي عنصر مع

myComponent.setTransferHandler(new FileDropHandler());

وهذا يعمل بالنسبة لي. أنا استخدامه مثل هذا (سكالا):

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
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top