Jonathan Beaudoin
Jonathan Beaudoin

Reputation: 2188

Dragging And Dropping Images

I'm making a program to edit images in Java. I was wondering if it's possible to drag an image off of a users desktop, onto the JPanel, and setting the image that was dragged as the background of the JPanel. Is that possible in Java? If so, how would I do it?

Upvotes: 2

Views: 2279

Answers (1)

Dan D.
Dan D.

Reputation: 32391

The short answer is: yes, it is possible.

There are several ways to do this, I will give you code for the simplest one: dragging an image file from somewhere to your Swing application. However, you can also copy an image to clipboard from an image editor and paste it there, but I think you don't need this. To implement this second use case, you will have to use the DataFlavor.imageFlavor instead of the DataFlavor.javaFileListFlavor that my example shows you. So, to test the code below, just add an instance of the MainPanel to a container and when the app runs, drag image files to the panel.

This is the implementation of the TransferHandler:

import java.awt.Cursor;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.TransferHandler;

public class ImageTransferHandler extends TransferHandler {
    private static final DataFlavor FILE_FLAVOR = DataFlavor.javaFileListFlavor;

    private MainPanel mainPanel;

    public ImageTransferHandler(MainPanel panel) {
        mainPanel = panel;
    }

    /**
     * The method to handle the transfer between the source of data and the
     * destination, which is in our case the main panel.
     */
    public boolean importData(JComponent c, Transferable t) {
        if (canImport(c, t.getTransferDataFlavors())) {
            if (transferFlavor(t.getTransferDataFlavors(), FILE_FLAVOR)) {
                try {
                    List<File> fileList = (List<File>) t.getTransferData(FILE_FLAVOR);
                    if (fileList != null && fileList.toArray() instanceof File[]) {
                        File[] files = (File[]) fileList.toArray();
                        mainPanel.addFiles(files);
                    }
                    return true;
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (UnsupportedFlavorException ex) {
                    ex.printStackTrace();
                }
            }
        }
        return false;
    }

    /**
     * Returns the type of transfer actions to be supported.
     */
    public int getSourceActions(JComponent c) {
        return COPY_OR_MOVE;
    }

    /**
     * Specifies the actions to be performed after the data has been exported.
     */
    protected void exportDone(JComponent c, Transferable data, int action) {
        c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    }

    /**
     * Returns true if the specified flavor is contained in the flavors array,
     * false otherwise.
     */
    private boolean transferFlavor(DataFlavor[] flavors, DataFlavor flavor) {
        boolean found = false;
        for (int i = 0; i < flavors.length && !found; i++) {
            found = flavors[i].equals(flavor);
        }
        return found;
    }

    /**
     * Returns true if the component can import the specified flavours, false
     * otherwise.
     */
    public boolean canImport(JComponent c, DataFlavor[] flavors) {
        for (int i = 0; i < flavors.length; i++) {
            if (FILE_FLAVOR.equals(flavors[i])) {
                return true;
            }
        }
        return false;
    }
}

This is the panel that I am adding the TransferHandler to and which draws the image as background:

public class MainPanel extends JPanel {
    private Image image;

    MainPanel() {
        setTransferHandler(new ImageTransferHandler(this));
    }

    void addFiles(File[] files) {
        for (File file : files) {
            try {
                image = ImageIO.read(file);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (image != null) {
            repaint();
        }
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.BLUE);
        int width = getWidth();
        int height = getHeight();
        drawImage((Graphics2D) g, width, height);
    }

    private void drawImage(Graphics2D g2, int width, int height) {
        if (image != null) {
            g2.drawImage(image, 0, 0, width, height, null);
        } else {
            g2.drawRect(10, 10, width - 20, height - 20);
        }
    }
}

Upvotes: 6

Related Questions