java - 具有动态生成的 HTML 的 JEditorPane.scrollToReference()

标签 java html swing anchor jeditorpane

我不知道如何 JEditorPane.scrollToReference() 旨在与动态生成的 HTML 页面一起使用。我想打开一个带有滚动到我选择的 anchor 的 JEditorPane 的对话框。无论我如何处理这个问题, View 总是在页面底部滚动。

作为一种丑陋的解决方法,我目前解析整个 HTML 文档以查找 anchor 标记,将它们的偏移量保存在 Map<String, Integer> 中。 ,然后我调用:

editorPane.setCaretPosition(anchorMap.get("anchor-name"));

...这甚至不会产生吸引人的结果,因为插入符号在可见矩形内的位置似乎无法预测,而且很少出现在窗口的顶部。我正在寻找一种更类似于浏览器的行为,其中锚定文本显示在可见区域的顶部。

下面是我尴尬的解决方法(“标题 6”上有一个 anchor )的屏幕截图,没有触摸滚动条:

screenshot

我想我遗漏了什么,但我不知道到底是什么。

我当前解决方法的来源:

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();
    }
}

最佳答案

问题可能是因为在执行 scrollToReference 时 Pane 还不可见或尚未布局,因此无法确定其大小。

scrollToReference 的实现有以下 block :

Rectangle r = modelToView(iter.getStartOffset());
if (r != null) {
   ...
   scrollRectToVisible(r);
}

在发布的示例中,anchor6 的矩形为 null,因为 View 尚不可见或其大小不是正值。

尝试这个肮脏的修复来延迟滚动:

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        editor.scrollToReference("anchor6");
    }
});
JOptionPane.showMessageDialog(new JPanel(), scroller, "",
        JOptionPane.PLAIN_MESSAGE);

关于java - 具有动态生成的 HTML 的 JEditorPane.scrollToReference(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11976781/

相关文章:

javascript - 使内部 div 可滚动

javascript - 单击后如何使按钮更改其位置?

Java Swing 在耗时任务期间显示 BusyIndi​​cator

java - 在 JPanel 上平铺图像,java

java - Java 中的 ActionPerformed 方法

java - 无法从 Google Compute Engine VM (Windows Server 2012) 访问 8080 端口上的 tomcat 服务器

java - 如何在java中使用for循环显示图像

java - 我如何告诉 Maven Artifact 已重命名?

java.lang.OutOfMemory错误: Java heap space in IntelliJ

javascript - 如何控制图像的大小