微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用html在swing组件上渲染内部图像?

我有以下代码

public static void main(String[] args) {
    JFrame frm = new JFrame();
    JEditorPane pane = new JEditorPane("text/html","<html><body>test<br><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACuklEQVR42sWVv09TURTH71AXE40xaRdXEwbD4ODiIFr6EwcXN1cnR0cXoyTWUjcH3n0dDG4aEwcaoqggWn8ERWtoKdVBoA2lxbj4BxzPt+eaPEn7nhDeleRDTr733vP9vtvXU0VE6n8i//79L5KdUKVUXtHobUXxnIAaGtawZzcNdxvgEIw2u0Va39SMa9A9DWvYE2aAKJ4WhpPTipySgBoa1rAnzAAxXPnalkvOjCL3iYAaGtawJ/QA650iaTYuPhVQQ7MbAOazAmqrAdb4hXOe8fW/EFBDsxdgmwM8Z/M5ATU0ewF+cACYvxRQQ7MS4NwtRd9xA/NsviCghoa1vQaIjP2ZcLnBxNng9E1F37p3yYH5awE1NKxhj18PeIx5J6YJ0Jtwaz/vUKObZwoDqW8VaL5xkfQr/gaUBdTQsOZ3Fr3h8dfENAGiCU5X79ygSW7oBKDf8JO/ZXMdamhB59AbHomcZ2KaADGIy+1r5HAjjabv+lMMYNA59ERveCS8L6s3QKV9lRxsfs+H9hn0RG94DAyw1L5CepEPfOCn8cFd7I/vGQa94dE3QJpfjMr2ZZr6oui+D/c+c8OP0tALNKz5nUVveKTzfQKcL6hfmQnVWxxEin9uR8YVlVuXSC+xsQE1NKxhj18pecsuq/LOl/AIc5KJM6M+ZHB9C60LpD+xuQE1NHO1mYAeI8yJnV/DAyZELIChJJvMtVKkK2xuQA0tKQGGAnpEjXlkT6M4xSazzTPk8ufpBVrKxm8BTGaap8itsvGyoSqatQCljWFya2LcoyaatQCPW8dJr/BnXzOsiGYtwKPmMdKrbFw3rIpmJUCaTR60jlLxK199Q0ANLW0jQJaHycPOQZpq8mTbMDRFy+bDDxDNjKsqjPC0XqAlvRMupACHmWHmbOCECylAxISIBk64kALs+99vkl5XSNCDZhMAAAAASUVORK5CYII=\"></body></html>");
    pane.setEditable(false);
    frm.getRootPane().setContentPane(pane);
    frm.pack();
    frm.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
    frm.setVisible(true);
}

要做的是使用base64编码在JEditorPane上渲染图像来存储图像.它不需要是base64,但这是我在尝试在JEditorPane上呈现HTML内容时所获得的,但我需要使用BufferedImage上的图像(它由应用程序生成),并且,我真的不想将图像保存到硬盘中的文件中.

我可以以某种方式在swing组件中显示BufferedImage以及HTML(在img标签给出的位置显示它 – HTML代码也由应用程序生成)?

解决方法

我不得不重写其中一个java类并扩展另一个,但是在JEditorPane的HTML下使BASE64图像工作.我会发布我的解决方案以防将来有人需要它…

首先,创建一个特殊的HTMLEditorKit,它将使用重写的ImageView类作为HTML.Tag.IMG

class BASE64HTMLEditorKit extends HTMLEditorKit {

    private static HTMLFactory factory = null;

    @Override
    public ViewFactory getViewFactory() {
        if (factory == null) {
            factory = new HTMLFactory() {

                @Override
                public View create(Element elem) {
                    AttributeSet attrs = elem.getAttributes();
                    Object elementName = attrs.getAttribute(AbstractDocument.ElementNameAttribute);
                    Object o = (elementName != null) ? null : attrs.getAttribute(StyleConstants.NameAttribute);
                    if (o instanceof HTML.Tag) {
                        HTML.Tag kind = (HTML.Tag) o;
                        if (kind == HTML.Tag.IMG) {
                            // HERE is the call to the special class...
                            return new BASE64ImageView(elem);
                        }
                    }
                    return super.create(elem);
                }
            };
        }
        return factory;
    }

}

完成后,基于openjdk代码实现特殊类.
下载源代码here,并打开文件openjdk / jdk / src / share / classes / javax / swing / text / html / ImageView.java.因为它几乎所有都是私有的,我发现更容易完全复制它然后更改加载BASE64图像所需的方法

private void loadImage() {
    String b64 = getBASE64Image();
    BufferedImage newImage = null;
    try (ByteArrayInputStream bais = new ByteArrayInputStream(DatatypeConverter.parseBase64Binary(b64))) {
        newImage = ImageIO.read(bais);
    } catch (IOException ex) {
        ...
    }
    image = newImage;
}

private String getBASE64Image() {
    String src = (String) getElement().getAttributes().getAttribute(HTML.Attribute.SRC);
    if (src == null) {
        return null;
    }
    return src.replaceFirst("data:image/png;base64,","");
}

getBASE64Image方法删除属性的非BASE64部分.
loadImage方法是必须更改的方法,如果它是公共的,将有助于从解决方案中删除大量代码

如果有人有更好的,最好更小(我的代码有1000行),请分享

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐