使用 HTMLEditorKit 缓慢解析动态 JTextPane
Slow parsing of dynamic JTextPane using 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>";
由于 HTMLEditor,我无法使用 pane.insertIcon。是否可能有某种容器将其设置为不可见,将内容添加到窗格,然后将容器设置为可见?
@StanislavL 的评论让我解决了问题,虽然不是他提供的 link,它没有用,我找不到原因,我仔细检查了 URL 是正确的,但是在设置缓存之后,窗格总是会为每张图片显示 "broken link" 图片。所以我找到了这个post,结合HTMLEditorKit的缓存机制的知识:
提到的代码:
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);
}
工作完美,现在正在工作。我还为 HTMLEditorKit 对 ImageView 进行了此更改:
public class MyImageView extends ImageView {
public MyImageView(Element elem) {
super(elem);
}
@Override
public Icon getNoImageIcon() {
return null;
}
@Override
public Icon getLoadingImageIcon() {
return null;
}
}
这不会再在窗格中显示任何损坏的 link 图片,也不会显示 "pre loading" 损坏的 link 图片。
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;
}
};
}
}
我遇到以下问题,我正在将 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>";
由于 HTMLEditor,我无法使用 pane.insertIcon。是否可能有某种容器将其设置为不可见,将内容添加到窗格,然后将容器设置为可见?
@StanislavL 的评论让我解决了问题,虽然不是他提供的 link,它没有用,我找不到原因,我仔细检查了 URL 是正确的,但是在设置缓存之后,窗格总是会为每张图片显示 "broken link" 图片。所以我找到了这个post,结合HTMLEditorKit的缓存机制的知识:
提到的代码:
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);
}
工作完美,现在正在工作。我还为 HTMLEditorKit 对 ImageView 进行了此更改:
public class MyImageView extends ImageView {
public MyImageView(Element elem) {
super(elem);
}
@Override
public Icon getNoImageIcon() {
return null;
}
@Override
public Icon getLoadingImageIcon() {
return null;
}
}
这不会再在窗格中显示任何损坏的 link 图片,也不会显示 "pre loading" 损坏的 link 图片。
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;
}
};
}
}