将 Image 对象复制到剪贴板时出错

yxo*_*xor 2 java clipboard

我试图将图像对象放入剪贴板,但出现了一个奇怪的错误。

这就是问题发生的地方。

ByteArrayInputStream bis = new ByteArrayInputStream(clipboardObject.data);
try(ObjectInput in = new ObjectInputStream(bis)) {
    ImageIcon img = (ImageIcon) in.readObject();
    ImageTransferable t = new ImageTransferable(img.getImage());
    Toolkit.getDefaultToolkit().getSystemClipboard()
            .setContents(t, null);
} catch(Exception e) {
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

这是我的ImageTransferable课。

static class ImageTransferable implements Transferable
{
    private Image image;

    public ImageTransferable (Image image)
    {
        this.image = image;
    }

    public Object getTransferData(DataFlavor flavor)
            throws UnsupportedFlavorException
    {
        if (isDataFlavorSupported(flavor))
        {
            return image;
        }
        else
        {
            throw new UnsupportedFlavorException(flavor);
        }
    }

    public boolean isDataFlavorSupported (DataFlavor flavor)
    {
        return flavor.equals(DataFlavor.imageFlavor);
    }

    public DataFlavor[] getTransferDataFlavors ()
    {
        return new DataFlavor[] { DataFlavor.imageFlavor };
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是我收到的错误。

ByteArrayInputStream bis = new ByteArrayInputStream(clipboardObject.data);
try(ObjectInput in = new ObjectInputStream(bis)) {
    ImageIcon img = (ImageIcon) in.readObject();
    ImageTransferable t = new ImageTransferable(img.getImage());
    Toolkit.getDefaultToolkit().getSystemClipboard()
            .setContents(t, null);
} catch(Exception e) {
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

Ale*_*der 5

这不是错误,只是调试信息

请注意,控制台中显示的异常实际上并不是错误,也不是真正从Toolkit.getDefaultToolkit().getSystemClipboard().setContents(t, null);方法调用中抛出的。

Java中的JPEG现在不支持透明度(https://bugs.openjdk.java.net/browse/JDK-8204188),但复制的图像实际上被压缩为PNG(或可能是其他格式)并且剪贴板设置正确即使是BufferedImage.TYPE_INT_ARGB图像类型。至少它对我来说适用于 JDK 14。

所以控制台中的这个异常只是一个调试信息(我已经研究了几个小时来理解它并发现它确实有效)。答案就在 OpenJDKsun.awt.windows.WClipboard.setContentsNative(Transferable contents)方法中:

         for (Long format : formatMap.keySet()) {
            DataFlavor flavor = formatMap.get(format);

            try {
                byte[] bytes = WDataTransferer.getInstance().
                    translateTransferable(contents, flavor, format);
                publishClipboardData(format, bytes);
            } catch (IOException e) {
                // Fix 4696186: don't print exception if data with
                // javaJVMLocalObjectMimeType failed to serialize.
                // May remove this if-check when 5078787 is fixed.
                if (!(flavor.isMimeTypeEqual(DataFlavor.javaJVMLocalObjectMimeType) &&
                      e instanceof java.io.NotSerializableException)) {
                    e.printStackTrace();
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

我希望这可以节省某人的时间。