Java HTMLDocument的(insertAfterEnd、insertAfterStart、insertBeforeEnd和insertBeforeStart)功能无法使用?

5
我有一个 JEditorPane,它以编程方式(在运行时)生成 HTML 并进行显示。迄今为止,当我添加一行时,我会重新创建整个 HTML 文本到字符串缓冲区中,然后将其传递给 JEditorPane.setText 方法。
现在创建的 HTML 变得非常大(最多可以达到几 MB),我只想在末尾添加新行,而不是重新生成所有 HTML 文本。
我试图在末尾附加文本的原因是要避免 Swing(或工具包?)再次渲染/解析整个文本。因为即使 HTML 生成不是在 EDT 中执行而是在另一个 swingworker 线程中执行,但“渲染”需要很长时间。或者最好的方法是显示渲染进度条,但这似乎不可能(对吗?)。
我的想法是简单地在末尾附加,但如果您有更好的想法,欢迎提出!
由于我的文本是在 HTML 表格中格式化的,所以我想将新文本附加到该表格的末尾。为此,我尝试使用 HTMLDocument 的 insertBeforeEnd,但即使我尝试了很多解决方案,也无法使其正常工作。请注意,我只有“table”标记。
以下是我的代码的一部分。
JEditorPane jep = new JEditorPane();
HTMLEditorKit kit = new HTMLEditorKit();
HTMLDocument doc = new HTMLDocument();

jep.setEditorKit(kit);
jep.setDocument(doc);

//setting dummy text within a HTML table
jep.setText("<table><tr><td>A line of text</td></tr><tr><td>Another line of text</td></tr></table>");

现在需要在此表格末尾添加一些文本。
//getting the Table Element
Element e = doc.getElement(doc.getDefaultRootElement(), StyleConstants.NameAttribute, HTML.Tag.TABLE);

请注意,元素似乎已被正确找到,因为System.out.println(e.getName())将返回“table”。
现在,
//inserting text at the end of the table
try {
        doc.insertBeforeEnd(e, "<tr><td>A New Line</td></tr>");
    } catch (BadLocationException ex) {
        System.out.println(ex);
    } catch (IOException ex) {
        System.out.println(ex);
    }

引发了一个异常:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: No HTMLEditorKit.Parser
at javax.swing.text.html.HTMLDocument.verifyParser(HTMLDocument.java:1500)
at javax.swing.text.html.HTMLDocument.insertBeforeEnd(HTMLDocument.java:1248)
...

编辑

我已经在这个问题的后续上发布了一个新问题,以下是链接:

https://stackoverflow.com/questions/9659209/jeditorpane-htmldocument-different-rendering-how-why

虽然@JoopEggen的答案能够解决问题,但字体渲染不同,我不明白为什么。因为我认为这是一个不同于此处发布的问题,所以我在另一个问题中提出了它(上面给出的链接)。但对于一些可能遇到相同问题的人,我设置了这个“编辑”来指向相应的线程。

1个回答

7
private HTMLDocument doc;
...
JTextPane jep = jTextPane1;
jep.setContentType("text/html");
jep.setText("<html><table><tr><td>A line of text</td></tr><tr><td>Another line of text</td></tr></table>");
doc = (HTMLDocument)jep.getStyledDocument();

在使用setText方法之前,需要确定文档类型并安装EditorKit。因此,请在此之后使用StyledDocument。再次使用setText("...")可以确保使用HTML。(您可以使用包含"< html >< b >H< /b >< i >ello< /i >< span style='color: #0ff078' >!!!< /span >"的JLabel或JButton)。

JTextPane比JEditorPane更高级(奇怪的命名)。它提供了StyledDocument,可以做更多的事情。

其余部分没有问题。


1
+1 setText() 实际上可以重新创建文档实例。检查 getDocument() 是否返回相同的实例。如果不是,请使用最新的文档实例。 - StanislavL
1
谢谢你们两个。我也理解了你们的建议,即JTextPane比JEditorPane更“高级”。我这么说是因为通过你们的解释,我删除了“jep.setDocument(doc)”,并在setText之后添加了“doc = (HTMLDocument)jep.getDocument();”,一切正常工作。非常感谢。但是,我需要进一步的信息。我需要一个非常快速的应用程序,这就是为什么我使用JEditorPane而不是JTextPane,因为据我所知,JEditorPane的“开销”较小于JTextPane。你同意吗?还是我应该切换到JTextPane(更“高级”)? - HpTerm
抱歉回复晚了。我没有经验。我觉得源代码结构不是很好。虽然从Java的开始就有这样的复杂性:编辑HTML等。 - Joop Eggen
非常感谢。这篇文章真是省了我不少时间。在过去的三天里,我一直在苦苦挣扎同样的问题。我通过setText()重新设置文档模型,但是由于之前调用getDocument()导致文档引用过期。在setText()后删除getDocument()并将其替换为getStyledDocument()解决了问题! - user396089

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接