スキップしてメイン コンテンツに移動

Drag & Drop Image File onto Java Swing Component

In this post I will show you how to achieve drag and drop image file onto Java Swing Component.
In short, implment TransferHandler which can transfer image file.

Code

Here is the code I wrote.
I defined common closure interface in order to give implementation flexibility.
The exec method of imageAcceptor will be called with Image object when drag & drop is succeeded.
package com.dukesoftware.utils.swing.drag;

import java.awt.Image;
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.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.imageio.ImageIO;
import javax.swing.TransferHandler;

import com.dukesoftware.utils.common.Closure;

public class ImageFileTransferHandler extends TransferHandler {

    private final static Set<String> SUPPORTED_SUFIXES = new HashSet<>(Arrays.asList(ImageIO.getReaderFileSuffixes()));

    private final Closure<Image> imageAcceptor;
    
    public ImageFileTransferHandler(Closure<Image> imageAcceptor){
        this.imageAcceptor = imageAcceptor;
    }
    
    @Override
    public boolean canImport(TransferSupport support) {
        if (!support.isDrop()) {
            return false;
        }
        
        return support.isDataFlavorSupported(DataFlavor.javaFileListFlavor);
    }
    
    @Override
    public boolean importData(TransferSupport support) {
        final Transferable transferable = support.getTransferable();
        try {
            final List<File> files = (List<File>)transferable.getTransferData(DataFlavor.javaFileListFlavor);
            if(files.size() <= 0){
                return false;
            }
            final File file = files.get(0);
            if(!isImageFile(file)){
                return false;
            }
            imageAcceptor.exec(ImageIO.read(file));
            return true;
        } catch (UnsupportedFlavorException e) {
            return false;
        } catch (IOException e) {
            return false;
        }
    }
    
    private static boolean isImageFile(File file){
        return canBeReadByImageIO(getExtension(file.getName()).toLowerCase());
    }
    
    private static boolean canBeReadByImageIO(String ext){
        return SUPPORTED_SUFIXES.contains(ext);
    }
    
    private static String getExtension(final String fname) {
        int dotNum = fname.lastIndexOf('.');
        return dotNum < 0 ? "" : fname.substring(dotNum + 1);
    }
}
package com.dukesoftware.utils.common;

public interface Closure<T> {

    void exec(T target);
}

How to Use

I added drag & drop functionality to AutoImageResizeCanvasDemo. I think it's quite easy.
Please feel free to improve the code so that it fits to your requirements!
package com.dukesoftware.utils.swing;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Image;
import java.io.IOException;

import javax.swing.JFrame;

import com.dukesoftware.utils.common.Closure;
import com.dukesoftware.utils.swing.drag.ImageFileTransferHandler;
import com.dukesoftware.utils.swing.others.AutoResizeImageCanvas;

public class AutoResizedImageCanvasDemo {

    public static void main(String[] args) throws IOException {
        final AutoResizeImageCanvas canvas = new AutoResizeImageCanvas();
        canvas.setTransferHandler(new ImageFileTransferHandler(new Closure<Image>() {
            
            @Override
            public void exec(Image target) {
                canvas.setImage(target);
                canvas.repaint();
            }
        }));

        // add to JFrame
        JFrame frame = new JFrame("Viewer");
        frame.getContentPane().add(canvas, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(640, 480));
        frame.pack();
        frame.setVisible(true);
    }

}

コメント