我无法弄清楚JEditorPane.scrollToReference()
如何与动态生成的HTML页面一起使用。我想打开一个带有JEditorPane的对话框,它会滚动到我选择的锚点。无论我如何解决问题,视图总是在页面底部滚动。
作为一个丑陋的解决方法,我目前正在解析整个HTML文档中的锚标记,将它们的偏移保存在Map<String, Integer>
中,然后我调用:
editorPane.setCaretPosition(anchorMap.get("anchor-name"));
...它甚至没有产生吸引人的结果,因为可见矩形内的插入符号位置看似不可预测,并且很少出现在窗口的顶部。我正在寻找更像浏览器的行为,其中锚定文本出现在可见区域的顶部。
下面是我笨拙的解决方法(“标题6”上有一个锚点)所发生的事情的屏幕截图,没有触及滚动条:
screenshot http://i49.tinypic.com/jkaj9s.png
我想我错过了一些东西,但我无法弄清楚到底是什么。
我当前解决方法的来源:
import javax.swing.*;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.*;
import javax.swing.text.html.HTMLEditorKit.*;
import javax.swing.text.html.parser.*;
import java.io.*;
import java.awt.*;
import java.util.HashMap;
public class AnchorTest
{
public static void main(String[] args)
{
final String html = generateLongPage();
final HashMap<String, Integer> anchors = anchorPositions(html);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JEditorPane editor = new JEditorPane("text/html", html);
JScrollPane scroller= new JScrollPane(editor);
scroller.setPreferredSize(new Dimension(400, 250));
//editor.scrollToReference("anchor6"); // doesn't work...
editor.setCaretPosition(anchors.get("anchor6")); //sorta works
JOptionPane.showMessageDialog(new JPanel(), scroller, "",
JOptionPane.PLAIN_MESSAGE);
}});
}
public static HashMap<String, Integer> anchorPositions(String html)
{
final HashMap<String, Integer> map = new HashMap<String, Integer>();
Reader reader = new StringReader(html);
HTMLEditorKit.Parser parser = new ParserDelegator();
try
{
ParserCallback cb = new ParserCallback()
{
public void handleStartTag(HTML.Tag t,
MutableAttributeSet a,
int pos)
{
if (t == HTML.Tag.A) {
String name =
(String)a.getAttribute(HTML.Attribute.NAME);
map.put(name, pos);
}
}
};
parser.parse(reader, cb, true);
}
catch (IOException ignore) {}
return map;
}
public static String generateLongPage()
{
StringBuilder sb = new StringBuilder(
"<html><head><title>hello</title></head><body>\n");
for (int i = 0; i < 10; i++) {
sb.append(String.format(
"<h1><a name='anchor%d'>header %d</a></h1>\n<p>", i, i));
for (int j = 0; j < 100; j++) {
sb.append("blah ");
}
sb.append("</p>\n\n");
}
return sb.append("</body></html>").toString();
}
}
答案 0 :(得分:4)
问题可能是因为在执行scrollToReference
时窗格尚未显示或尚未布局,因此无法确定其大小。
scrollToReference
的实施具有以下块:
Rectangle r = modelToView(iter.getStartOffset());
if (r != null) {
...
scrollRectToVisible(r);
}
在发布的示例中,null
的矩形为anchor6
,因为视图尚未显示或其大小不正。
尝试这个脏修复来延迟滚动:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
editor.scrollToReference("anchor6");
}
});
JOptionPane.showMessageDialog(new JPanel(), scroller, "",
JOptionPane.PLAIN_MESSAGE);