使用TransferHandler拖放图像

时间:2013-12-15 14:09:16

标签: java image drag-and-drop

我正在尝试制作简单的Java应用程序,将图像拖放到JFabel上JLabel,但没有运气。我稍后会在我的程序中使用此功能,它将接收丢弃的图像,调整其大小然后调整亮度。制作它并保存该图像以进行进一步编辑的最简单方法是什么?

这是我的代码,它只收到删除的文本:

import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.TransferHandler;

class DragNDrop extends JFrame {
        JLabel label;

        public DragNDrop() {

            setTitle("Simple Drag & Drop");
            setLayout(null);

            label = new JLabel();
            label.setBounds(0, 0, 200, 200);

            add(label);
            label.setTransferHandler(new TransferHandler("text"));

            setSize(200, 200);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setLocationRelativeTo(null);
            setVisible(true);
    }

    public static void main(String[] args) {
            new DragNDrop();
    }
}

1 个答案:

答案 0 :(得分:3)

使用the constructor that takes a String创建TransferHandler时,您创建的TransferHandler只能在同一JVM中执行传输。

new TransferHandler("text")创建一个TransferHandler,它传输JLabel(或任何其他组件或bean)的'text'属性。如果要拖动图像,则需要Image类型的属性。 JLabel没有Image类型的属性,但它具有Icon类型的属性。如果使用它,拖动源必须提供Icon类型的数据,并且您仍然只能接受来自同一JVM的数据。

如果要接受来自任何应用程序的任何图像数据,则必须编写自定义TransferHandler。图像可以采用多种形式,但一些常见的形式是:

  1. java.awt.Image,由DataFlavor.imageFlavor表示。
  2. 文件列表(List<File>),由DataFlavor.javaFileListFlavor表示。顾名思义,这通常是用户拖动文件的结果。
  3. 二进制数据(通常以InputStream的形式),其MIME类型(例如“image / png”)表示字节是图像。
  4. 您的自定义TransferHandler可能如下所示:

    private static class ImageHandler
    extends TransferHandler {
        private static final long serialVersionUID = 1;
    
        private boolean isReadableByImageIO(DataFlavor flavor) {
            Iterator<?> readers = ImageIO.getImageReadersByMIMEType(
                flavor.getMimeType());
            if (readers.hasNext()) {
                Class<?> cls = flavor.getRepresentationClass();
                return (InputStream.class.isAssignableFrom(cls) ||
                        URL.class.isAssignableFrom(cls) ||
                        File.class.isAssignableFrom(cls));
            }
    
            return false;
        }
    
        @Override
        public boolean canImport(TransferSupport support) {
            if (support.getUserDropAction() == LINK) {
                return false;
            }
    
            for (DataFlavor flavor : support.getDataFlavors()) {
                if (flavor.equals(DataFlavor.imageFlavor) ||
                    flavor.equals(DataFlavor.javaFileListFlavor) ||
                    isReadableByImageIO(flavor)) {
    
                    return true;
                }
            }
            return false;
        }
    
        @Override
        public boolean importData(TransferSupport support) {
            if (!(support.getComponent() instanceof JLabel)) {
                return false;
            }
            if (!canImport(support)) {
                return false;
            }
    
            // There are three types of DataFlavor to check:
            // 1. A java.awt.Image object (DataFlavor.imageFlavor)
            // 2. A List<File> object (DataFlavor.javaFileListFlavor)
            // 3. Binary data with an image/* MIME type.
    
            if (support.isDataFlavorSupported(DataFlavor.imageFlavor)) {
                try {
                    Image image = (Image)
                        support.getTransferable().getTransferData(
                            DataFlavor.imageFlavor);
    
                    JLabel label = (JLabel) support.getComponent();
                    label.setIcon(new ImageIcon(image));
                    return true;
                } catch (UnsupportedFlavorException | IOException e) {
                    e.printStackTrace();
                }
            }
    
            if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                try {
                    Iterable<?> list = (Iterable<?>)
                        support.getTransferable().getTransferData(
                            DataFlavor.javaFileListFlavor);
                    Iterator<?> files = list.iterator();
                    if (files.hasNext()) {
                        File file = (File) files.next();
                        Image image = ImageIO.read(file);
    
                        JLabel label = (JLabel) support.getComponent();
                        label.setIcon(new ImageIcon(image));
                        return true;
                    }
                } catch (UnsupportedFlavorException | IOException e) {
                    e.printStackTrace();
                }
            }
    
            for (DataFlavor flavor : support.getDataFlavors()) {
                if (isReadableByImageIO(flavor)) {
                    try {
                        Image image;
    
                        Object data =
                            support.getTransferable().getTransferData(flavor);
                        if (data instanceof URL) {
                            image = ImageIO.read((URL) data);
                        } else if (data instanceof File) {
                            image = ImageIO.read((File) data);
                        } else {
                            image = ImageIO.read((InputStream) data);
                        }
    
                        JLabel label = (JLabel) support.getComponent();
                        label.setIcon(new ImageIcon(image));
                        return true;
                    } catch (UnsupportedFlavorException | IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    
            return false;
        }
    }
    

    一些额外的建议:在实践中,在编写功能齐全的应用程序时,您应该使用LayoutManagers。你可以从你的代码中删除setLayout(null)和label.setBounds行,你会得到完全相同的结果,因为JFrame的默认contentPane使用BorderLayout,而单参数add方法将你的JLabel放入BorderLayout的中心,这意味着它填满了整个框架。