使用TransferHandler拖放图像 [英] Drag and drop image with TransferHandler

查看:156
本文介绍了使用TransferHandler拖放图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to make simple java app to drag and drop image into JLabel which is on JFrame with no luck. I will later use this functionality in my program which will receive dropped image, resize it and then adjust brightness. What is simplest way to make it and to save that image for further editing?

这是我的代码只收到丢弃的文本:

Here is my code which only receives dropped text:

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();
    }
}


推荐答案

使用获取字符串的构造函数,您创建一个只能在同一JVM中执行传输的TransferHandler。

When you create a TransferHandler using the constructor that takes a String, you create a TransferHandler that can only perform transfers within the same JVM.

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

new TransferHandler("text") creates a TransferHandler that transfers the 'text' property of JLabel (or any other component or bean). If you want to drag images, you need a property of type Image. JLabel has no properties of type Image, but it has a property of type Icon. If you use that, the drag source must supply data of type Icon, and you will still have the limitation of only accepting data from the same JVM.

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

If you want to accept any Image data from any application, you must write a custom TransferHandler. Images can take a number of forms, but some common forms are:


  1. java.awt.Image,由 DataFlavor.imageFlavor

  2. 文件列表(列表<文件> ),由 DataFlavor.javaFileListFlavor 。顾名思义,这通常是用户拖动文件的结果。

  3. 其MIME类型(例如image / png)的二进制数据(通常以InputStream的形式)表示字节是图像。

  1. A java.awt.Image, represented by DataFlavor.imageFlavor.
  2. A List of Files (List<File>), represented by DataFlavor.javaFileListFlavor. As the name suggests, this usually is the result of the user's dragging files.
  3. Binary data (usually in the form of an InputStream) whose MIME type (such as "image/png") indicates the bytes are an image.

您的自定义TransferHandler可能如下所示:

Your custom TransferHandler, then, might look like this:

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;
    }
}

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

Some additional advice: In practice, when writing a full-featured application, you should be using LayoutManagers. You could remove the setLayout(null) and label.setBounds lines from your code, and you would get exactly the same result, because a JFrame's default contentPane uses a BorderLayout, and the single-argument add method places your JLabel in the center of that BorderLayout, which means it fills the entire frame.

这篇关于使用TransferHandler拖放图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆