【问题标题】:Drag and drop image with TransferHandler使用 TransferHandler 拖放图像
【发布时间】:2013-12-15 14:09:15
【问题描述】:

我正在尝试制作简单的 java 应用程序来将图像拖放到 JFrame 上的 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();
    }
}

【问题讨论】:

  • 首先,new TransferHandler("text") 创建了一个使用 JLabel 的 getTextsetText 方法的 TransferHandler,因此它不可能处理图像。其次,公共的 TransferHandler 构造函数创建了一个只适用于其他 Java 组件的 TransferHandler;它不会接受来自非 Java 应用程序的拖动数据。您必须编写自己的 TransferHandler 子类。
  • 但是 TransferHandler 可以处理从外部 java 应用程序中删除的文本。我不知道怎么写那个子类..
  • 您可以在什么操作系统中将文本拖放到您的应用程序中?您从哪个其他应用程序拖动文本?我无法让它在 Linux 或 Windows 7 中工作。TransferHandler 默认实现的源代码不允许使用除 DataFlavor.javaJVMLocalObjectMimeType 之外的任何 DataFlavor。
  • 我在 Windows 8 中删除文本,从 Netbeans 中选择它并放到应用程序中。

标签: java image drag-and-drop


【解决方案1】:

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

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

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

  1. 一个 java.awt.Image,由DataFlavor.imageFlavor 表示。
  2. 文件列表 (List<File>),由 DataFlavor.javaFileListFlavor 表示。顾名思义,这通常是用户拖动文件的结果。
  3. 二进制数据(通常采用 InputStream 的形式),其 MIME 类型(例如“image/png”)指示字节为图像。

然后,您的自定义 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,这意味着它填满了整个框架。

【讨论】:

    猜你喜欢
    • 2012-07-12
    • 1970-01-01
    • 1970-01-01
    • 2021-05-25
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多