小编典典

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

java

我有以下代码:

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代码也是由应用程序生成的)吗?


阅读 221

收藏
2020-11-26

共1个答案

小编典典

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

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

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代码实现特殊类。在此处下载源代码,然后打开文件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行代码),请分享…

2020-11-26