本文目录导读:

基于您提供的关键词 JEditorPane HTMLEditorKit Parser Subscribe,您可能是在 Java Swing 开发中遇到了以下两种常见情况之一:
- 如何监听/订阅
JEditorPane的 HTML 解析完成事件? - 如何自定义 HTML 解析器 (
ParserCallback) 来拦截或处理特定的 HTML 标签?
下面针对这两个场景提供详细解答。
订阅/监听 HTML 解析完成事件
JEditorPane 在使用 HTMLEditorKit 加载 HTML 内容时,解析和渲染是异步进行的,Java Swing 本身并没有直接提供一个“解析完成”的事件监听器(如 addParseListener),但可以通过以下几种曲线救国的方式实现“订阅”效果。
方法 1:使用 PropertyChangeListener(推荐)
这是最标准的方法,当编辑器内容加载完毕后,page 属性会发生变化。
import javax.swing.*;
import javax.swing.text.html.HTMLEditorKit;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
public class HtmlParseListener {
public static void main(String[] args) {
JFrame frame = new JFrame();
JEditorPane editorPane = new JEditorPane();
editorPane.setEditorKit(new HTMLEditorKit());
editorPane.setEditable(false);
// ★ 订阅页面加载完成事件
editorPane.addPropertyChangeListener("page", new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println("HTML 解析完成,页面已加载!");
// 在这里执行你需要在解析完成后做的事情
// 设置光标位置、修改文档、添加链接监听器等
}
});
// 加载 HTML
editorPane.setText("<html><body><h1>Hello, World!</h1></body></html>");
frame.add(new JScrollPane(editorPane));
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
方法 2:继承 HTMLEditorKit 并重写 createParser
如果你需要在解析过程中进行拦截(而不仅仅是完成时),可以自定义 ParserCallback。
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;
import javax.swing.text.html.parser.DTD;
import javax.swing.text.html.HTML;
import javax.swing.text.MutableAttributeSet;
import java.io.*;
public class CustomHtmlEditorKit extends HTMLEditorKit {
@Override
public Parser getParser() {
// 返回一个自定义的解析器,或者像下面这样返回默认解析器
// 但为了拦截回调,通常需要自定义 Callback
return super.getParser();
}
// 另一种方法:如果你想要完全控制解析,可以这样
public static void parseWithCustomCallback(String html, final HTMLEditorKit.ParserCallback customCallback) {
ParserDelegator parser = new ParserDelegator();
try {
Reader reader = new StringReader(html);
// 使用你的自定义 Callback
parser.parse(reader, customCallback, true);
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 使用示例
public static void main(String[] args) {
String htmlContent = "<html><body><p>Test</p></body></html>";
parseWithCustomCallback(htmlContent, new HTMLEditorKit.ParserCallback() {
@Override
public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
System.out.println("开始标签: " + t + " 位置: " + pos);
// ★ 这里就是订阅点:每当解析器遇到开始标签就会调用
}
@Override
public void handleText(char[] data, int pos) {
System.out.println("文本: " + new String(data));
}
@Override
public void handleEndTag(HTML.Tag t, int pos) {
System.out.println("结束标签: " + t);
}
@Override
public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
System.out.println("单标签: " + t);
}
@Override
public void handleError(String errorMsg, int pos) {
System.err.println("解析错误: " + errorMsg);
}
});
}
}
替换默认解析器以订阅底层解析事件
如果你需要全局替换 JEditorPane 使用的解析器(ParserDelegator),可以通过覆盖 HTMLEditorKit 的 getParser() 方法来实现,不过通常情况下,直接使用 PropertyChangeListener 或自定义 ParserCallback 就足够了。
应对“订阅”需求的方案
| 需求 | 解决方案 | 关键代码/类 |
|---|---|---|
| 解析完成后执行动作 | addPropertyChangeListener("page", ...) |
JEditorPane |
| 在解析过程中拦截标签 | 自定义 ParserCallback |
HTMLEditorKit.ParserCallback |
| 完全自定义解析器 | 继承 HTMLEditorKit 并重写 getParser() |
HTMLEditorKit, ParserDelegator |
如果您能提供更多上下文(“我在做一个富文本编辑器,想在解析某个特定标签时触发一个动作”),我可以给出更精确的代码示例。