本文目录导读:

我来详细介绍 JEditorPane、HTMLEditorKit 和解析器监控(Parser Monitor)的相关内容。
JEditorPane 与 HTMLEditorKit 概述
JEditorPane
- Swing 中的轻量级 HTML 渲染组件
- 支持 HTML 3.2 和部分 CSS 功能
- 使用
HTMLEditorKit作为默认编辑器
HTMLEditorKit
JEditorPane editorPane = new JEditorPane();
HTMLEditorKit kit = new HTMLEditorKit();
editorPane.setEditorKit(kit);
editorPane.setContentType("text/html");
解析器监控(Parser Monitor)
基本实现
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;
import javax.swing.text.*;
public class HTMLParserMonitor {
public static void main(String[] args) {
JEditorPane editorPane = new JEditorPane();
// 创建自定义的 HTMLEditorKit
HTMLEditorKit kit = new HTMLEditorKit() {
@Override
public Document createDefaultDocument() {
HTMLDocument doc = (HTMLDocument) super.createDefaultDocument();
// 设置解析器监控
doc.setParser(new DocumentParser() {
@Override
public void parse(Reader r, HTMLDocument doc) throws IOException {
System.out.println("开始解析 HTML...");
super.parse(r, doc);
System.out.println("HTML 解析完成");
}
});
return doc;
}
};
editorPane.setEditorKit(kit);
}
}
完整的监控实现
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;
import java.io.*;
public class ParserMonitorExample {
public static class MonitoredHTMLEditorKit extends HTMLEditorKit {
@Override
public Document createDefaultDocument() {
HTMLDocument doc = new HTMLDocument() {
@Override
public void parse(Reader r) throws IOException {
System.out.println("=== 开始解析 HTML 文档 ===");
long startTime = System.currentTimeMillis();
// 添加解析监听器
addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
System.out.println("插入内容: " + e.getOffset() + ", 长度: " + e.getLength());
}
@Override
public void removeUpdate(DocumentEvent e) {
System.out.println("删除内容: " + e.getOffset() + ", 长度: " + e.getLength());
}
@Override
public void changedUpdate(DocumentEvent e) {
System.out.println("修改内容: " + e.getOffset() + ", 长度: " + e.getLength());
}
});
// 执行解析
try {
super.parse(r);
} catch (Exception e) {
System.err.println("解析错误: " + e.getMessage());
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("=== 解析完成,耗时: " + (endTime - startTime) + "ms ===");
}
};
return doc;
}
@Override
public ViewFactory getViewFactory() {
return new HTMLFactory() {
@Override
public View create(Element elem) {
View view = super.create(elem);
if (view != null) {
System.out.println("创建视图: " + view.getClass().getSimpleName()
+ " 元素: " + elem.getName());
}
return view;
}
};
}
}
// 使用示例
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("HTML Parser Monitor");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);
JEditorPane editorPane = new JEditorPane();
MonitoredHTMLEditorKit kit = new MonitoredHTMLEditorKit();
editorPane.setEditorKit(kit);
// 设置 HTML 内容
String html = "<html><body><h1>标题</h1><p>段落内容</p></body></html>";
editorPane.setText(html);
JScrollPane scrollPane = new JScrollPane(editorPane);
frame.add(scrollPane);
frame.setVisible(true);
// 监控解析过程
monitorParsing(editorPane);
});
}
private static void monitorParsing(JEditorPane editorPane) {
HTMLDocument doc = (HTMLDocument) editorPane.getDocument();
doc.addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
printDocumentInfo(doc);
}
@Override
public void removeUpdate(DocumentEvent e) {
printDocumentInfo(doc);
}
@Override
public void changedUpdate(DocumentEvent e) {
printDocumentInfo(doc);
}
});
}
private static void printDocumentInfo(HTMLDocument doc) {
System.out.println("\n文档信息:");
System.out.println("元素数量: " + doc.getLength());
System.out.println("段落数量: " + countElements(doc, HTML.Tag.P));
System.out.println("标题数量: " + countElements(doc, HTML.Tag.H1));
System.out.println("-------------------");
// 列出所有元素
Element root = doc.getDefaultRootElement();
printElementTree(root, 0);
}
private static int countElements(HTMLDocument doc, HTML.Tag tag) {
int count = 0;
Element root = doc.getDefaultRootElement();
count = countElementsRecursive(root, tag);
return count;
}
private static int countElementsRecursive(Element element, HTML.Tag tag) {
int count = 0;
AttributeSet attrs = element.getAttributes();
Object name = attrs.getAttribute(StyleConstants.NameAttribute);
if (name == tag) {
count++;
}
for (int i = 0; i < element.getElementCount(); i++) {
count += countElementsRecursive(element.getElement(i), tag);
}
return count;
}
private static void printElementTree(Element element, int indent) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < indent; i++) {
sb.append(" ");
}
AttributeSet attrs = element.getAttributes();
Object name = attrs.getAttribute(StyleConstants.NameAttribute);
sb.append("元素: ").append(name != null ? name.toString() : "unknown");
if (element.isLeaf()) {
sb.append(" [leaf]");
try {
int start = element.getStartOffset();
int end = element.getEndOffset();
Document doc = element.getDocument();
String content = doc.getText(start, end - start);
sb.append(" 内容: '").append(content.trim()).append("'");
} catch (BadLocationException e) {
// ignore
}
}
System.out.println(sb.toString());
for (int i = 0; i < element.getElementCount(); i++) {
printElementTree(element.getElement(i), indent + 1);
}
}
}
高级监控功能
自定义标签处理器
public class CustomTagHandler extends HTMLDocument.HTMLReader.TagAction {
@Override
public void start(HTMLDocument.HTMLReader.TagAction t, HTML.Tag tag, MutableAttributeSet attrs) {
System.out.println("开始标签: " + tag);
if (attrs != null) {
System.out.println(" 属性: " + attrs);
}
super.start(t, tag, attrs);
}
@Override
public void end(HTMLDocument.HTMLReader.TagAction t, HTML.Tag tag) {
System.out.println("结束标签: " + tag);
super.end(t, tag);
}
}
性能监控
public class PerformanceMonitor {
private long startTime;
private int elementCount;
public void startTracking() {
startTime = System.currentTimeMillis();
elementCount = 0;
}
public void trackElement(Element element) {
elementCount++;
}
public void printReport() {
long duration = System.currentTimeMillis() - startTime;
System.out.println("解析性能报告:");
System.out.println(" 元素总数: " + elementCount);
System.out.println(" 解析耗时: " + duration + "ms");
System.out.println(" 平均速度: " + (elementCount / (duration / 1000.0)) + " 元素/秒");
}
}
注意事项
- 线程安全:Swing 组件需要在事件调度线程(EDT)中操作
- 性能影响:监控功能会增加性能开销
- 内存使用:大量文档解析时注意内存管理
- 解析限制:Swing HTML 解析器支持有限,复杂 HTML 可能需要其他库
这个监控系统可以帮助开发人员了解 HTML 文档的解析过程,调试渲染问题,以及优化性能。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播