Медленный парсинг динамического JTextPane с использованием HTMLEditorKit

У меня следующая проблема: я использую JTextPane с HTMLEditorKit и динамически добавляю контент на панель. Контент может занимать несколько строк, а также содержать множество изображений (маленькие значки). Теперь проблема в том, что если я вставлю, например, кучу текста со значками, через:

editorKit.insertHTML(doc, doc.getLength(), htmlCode, 0, 0, null);

В результате изображения в html-коде долго появляются на экране (~ 1 секунда):

введите описание изображения здесь

Вопрос: есть ли способ буферизовать изображения, отображаемые на панели, если это html-код, через:

imgsrc = "file:/" + imgSRCOnHDD;
imgsrc = imgsrc.replace("\\", "/");
imgSub = "<img height=\"18\" width=\"18\" style=\"vertical-align:middle;\" src='" + imgsrc + "'></img>";

Я не могу использовать pane.insertIcon из-за HTMLEditor. Может быть, есть какой-то контейнер, который делает его невидимым, добавляя контент на панель, а затем устанавливая контейнер видимым?


person M. H.    schedule 23.03.2017    source источник
comment
Может SwingWorker<HTMLDocument, HTMLDocument>? Профиль, чтобы быть уверенным.   -  person trashgod    schedule 23.03.2017
comment
java-sl.com/tip_local_images.html вы можете попытаться сохранить изображения в собственном кеше   -  person StanislavL    schedule 23.03.2017
comment
большое спасибо за подсказку, что решила проблему   -  person M. H.    schedule 23.03.2017


Ответы (1)


Комментарий @StanislavL привел к тому, что я решил проблему, хотя и не предоставленная им ссылка, она не сработала, и я не мог понять, почему, URL-адреса были правильными, я дважды проверил, но после установки кеша на панели всегда будет отображаться «неработающая ссылка "картинка для каждого изображения. Итак, я нашел этот пост, зная о механизме кеширования HTMLEditorKit:

https://stackoverflow.com/a/27669916/7377320

Упомянутый код:

public class ImageCache extends Hashtable {

    public Object get(Object key) {

        Object result = super.get(key);

        if (result == null){

            result = Toolkit.getDefaultToolkit().createImage((URL) key);
            put(key, result);
        }

        return result;
    }
}

...

Dictionary cache = (Dictionary) pane.getDocument().getProperty("imageCache");

if (cache == null) {

    cache = new ImageCache();
    pane.getDocument().putProperty("imageCache", cache);
}

Сработало безупречно, и сейчас работает. Я также внес это изменение в ImageView для HTMLEditorKit:

public class MyImageView extends ImageView {

    public MyImageView(Element elem) {
        super(elem);
    }

    @Override
    public Icon getNoImageIcon() {
        return null;
    }

    @Override
    public Icon getLoadingImageIcon() {
        return null;
    }
}

При этом больше не будут отображаться изображения битых ссылок на панели, а также изображение битых ссылок "перед загрузкой".

HTMLEditorKit:

public class MyHTMLEditorKit extends HTMLEditorKit {

    @Override
    public ViewFactory getViewFactory() {

        return new HTMLEditorKit.HTMLFactory() {

            public View create(Element e) {

                View v = super.create(e);

                Object o = e.getAttributes().getAttribute(StyleConstants.NameAttribute);

                if (o instanceof HTML.Tag) {

                    HTML.Tag kind = (HTML.Tag) o;

                    if (kind == HTML.Tag.IMG) {
                        return new MyImageView(e);
                    }
                }

                if (v instanceof InlineView) {

                    return new InlineView(e) {

                        public int getBreakWeight(int axis, float pos, float len) {
                            return View.GoodBreakWeight;
                        }

                        public View breakView(int axis, int p0, float pos, float len) {

                            if (axis == View.X_AXIS) {

                                checkPainter();

                                int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len);
                                if (p0 == getStartOffset() && p1 == getEndOffset()) {
                                    return this;
                                }

                                return createFragment(p0, p1);
                            }

                            return this;
                        }
                    };
                } else if (v instanceof ParagraphView) {

                    return new ParagraphView(e) {

                        protected javax.swing.SizeRequirements calculateMinorAxisRequirements(int axis, javax.swing.SizeRequirements r) {

                            if (r == null) {
                                r = new javax.swing.SizeRequirements();
                            }

                            float pref = layoutPool.getPreferredSpan(axis);
                            float min = layoutPool.getMinimumSpan(axis);

                            // Don't include insets, Box.getXXXSpan will include them. 
                            r.minimum = (int) min;
                            r.preferred = Math.max(r.minimum, (int) pref);
                            r.maximum = Integer.MAX_VALUE;
                            r.alignment = 0.5f;

                            return r;
                        }

                    };
                }

                return v;
            }
        };
    }
}
person M. H.    schedule 23.03.2017