Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drag'n drop files from the OS to Java application (Swing)

Let me start by saying that I have been reading the drag'n drop tutorial and similar questions asked on SO, but unfortunately I have only gotten more confused about this matter. What I want to achieve is relatively simple so I am surprised that it got me in so much trouble already. I am writing a small utility application which will consolidate a bunch of result files (custom defined xml-type) into a large tab-separated text file. Most of the functionality is already coded, however I wanted to make a decent GUI for it.

What I want is to be able to drag'n drop files into a component (for instance JTextArea) in a nice and gracious way (read: not full paths, but instead a small icon and name). I would like to be able to supply a JFileChooser to browse for files as well. I will then parse the files sequentially to produce the matrix I want.

What I have learned so far is that the framework is already there however any additional functionality needs to be custom built. I have created a test GUI in Netbeans and tried to drag a bunch of files onto a JTextArea, but they appear as file paths, and admittedly it looks very ugly.

I would really appreciate any tips and guidance on how to solve (or clarify) this problem in a neat way. Note that I do intend to use the software on multiple different OS (Mac,Win and Linux).

EDIT: the code I have so far is based on one of the examples from Sun tutorials and is as follows

import java.awt.datatransfer.*;
import java.awt.event.*;
import java.awt.*;
import java.io.*;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.text.*;

public class ConsolidatorDemo extends JPanel implements ActionListener {
    private static final long serialVersionUID = -4487732343062917781L;
    JFileChooser fc;
    JButton clear;
    JTextArea dropZone, console;
    JSplitPane childSplitPane, parentSplitPane;
    PrintStream ps;

  public ConsolidatorDemo() {
    super(new BorderLayout());

    fc = new JFileChooser();;
    fc.setMultiSelectionEnabled(true);
    fc.setDragEnabled(true);
    fc.setControlButtonsAreShown(false);
    fc.setFileSelectionMode(JFileChooser.FILES_ONLY);               


    JPanel fcPanel = new JPanel(new BorderLayout());
    fcPanel.add(fc, BorderLayout.CENTER);

    clear = new JButton("Clear All");
    clear.addActionListener(this);
    JPanel buttonPanel = new JPanel(new BorderLayout());
    buttonPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    buttonPanel.add(clear, BorderLayout.LINE_END);

    JPanel leftUpperPanel = new JPanel(new BorderLayout());
    leftUpperPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    leftUpperPanel.add(fcPanel, BorderLayout.CENTER);
    leftUpperPanel.add(buttonPanel, BorderLayout.PAGE_END);


    JScrollPane leftLowerPanel = new javax.swing.JScrollPane();
    leftLowerPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    dropZone = new JTextArea();
    dropZone.setColumns(20);
    dropZone.setLineWrap(true);
    dropZone.setRows(5);
    dropZone.setDragEnabled(true);
    dropZone.setDropMode(javax.swing.DropMode.INSERT);
    dropZone.setBorder(new TitledBorder("Selected files/folders"));
    leftLowerPanel.setViewportView(dropZone);

    childSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
            leftUpperPanel, leftLowerPanel);
    childSplitPane.setDividerLocation(400);
    childSplitPane.setPreferredSize(new Dimension(480, 650));

    console = new JTextArea();
    console.setColumns(40);
    console.setLineWrap(true);
    console.setBorder(new TitledBorder("Console"));

    parentSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                    childSplitPane, console);
    parentSplitPane.setDividerLocation(480);
    parentSplitPane.setPreferredSize(new Dimension(800, 650));

    add(parentSplitPane, BorderLayout.CENTER);

}

public void setDefaultButton() {
    getRootPane().setDefaultButton(clear);
}

public void actionPerformed(ActionEvent e) {
    if (e.getSource() == clear) {
        dropZone.setText("");

    }
}

/**
 * Create the GUI and show it. For thread safety,
 * this method should be invoked from the
 * event-dispatching thread.
 */
private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    try {
      //UIManager.setLookAndFeel("de.javasoft.plaf.synthetica.SyntheticaBlackStarLookAndFeel");
        for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    }catch (Exception e){
      e.printStackTrace();
    }

    //Create and set up the window.
    JFrame frame = new JFrame("Consolidator!");
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    //Create and set up the menu bar and content pane.
    ConsolidatorDemo demo = new ConsolidatorDemo();
    demo.setOpaque(true); //content panes must be opaque
    frame.setContentPane(demo);

    //Display the window.
    frame.pack();
    frame.setVisible(true);
    demo.setDefaultButton();
}

public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}
like image 442
posdef Avatar asked Feb 08 '12 11:02

posdef


People also ask

Does Java have drag and drop?

Drag and drop enables data transfer across Java programming language and native applications, between Java programming language applications, and within a single Java programming language application.

What are Swing applications in Java?

Swing in java is part of Java foundation class which is lightweight and platform independent. It is used for creating window based applications. It includes components like button, scroll bar, text field etc. Putting together all these components makes a graphical user interface.

Is Java Swing still good?

Absolutely yes. Legacy swing applications are still supported and enhanced. There is no alternative for that. And if you are making applications like IDE's, SWING is still preferred.


1 Answers

here's a quick snippet to import the actual Files into a JList (as opposed to importing its String representation into a text component) and use a custom renderer to present it nicely. It's adapted from the BasicDnD (in the tutorial):

    fileDropper = new JList(new DefaultListModel());
    fileDropper.setDragEnabled(true);
    leftLowerPanel.setViewportView(fileDropper);

    TransferHandler handler =   new TransferHandler() {

        @Override
        public boolean canImport(TransferHandler.TransferSupport info) {
            // we only import FileList
            if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                return false;
            }
            return true;
        }

        @Override
        public boolean importData(TransferHandler.TransferSupport info) {
            if (!info.isDrop()) {
                return false;
            }

            // Check for FileList flavor
            if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                displayDropLocation("List doesn't accept a drop of this type.");
                return false;
            }

            // Get the fileList that is being dropped.
            Transferable t = info.getTransferable();
            List<File> data;
            try {
                data = (List<File>)t.getTransferData(DataFlavor.javaFileListFlavor);
            } 
            catch (Exception e) { return false; }
            DefaultListModel model = (DefaultListModel) fileDropper.getModel();
            for (File file : data) {
                model.addElement(file);
            }
            return true;
        }

        private void displayDropLocation(String string) {
            System.out.println(string);
        }
    };
    fileDropper.setTransferHandler(handler);
    fileDropper.setCellRenderer(new DefaultListRenderer(
          StringValues.FILE_NAME, IconValues.FILE_ICON));

Couldn't resist to showing SwingX renderer config :-) In core java, you would do it manually, something like

   class MyRenderer extends DefaultListCellRenderer {

        @Override
        public Component getListCellRendererComponent(...) {
            super.getList...
            if (value instanceof File) {
                setText(FileSystemView.getFileSystemView().getDisplayName(value);
                setIcon(FileSystemView.getFileSystemView().getSystemIcon(value);
            } 
            return this;
        }

   }
like image 148
kleopatra Avatar answered Sep 21 '22 14:09

kleopatra