本文目录导读:

我来详细解释 JEditorPane、HTMLEditorKit、Parser 和 Handler 这几个核心组件及其关系。
这是 Java Swing 中用于显示和编辑 HTML 内容的组件体系,它们共同构成了一个完整的内容处理管道。
核心组件关系
graph TB
A[JEditorPane] --> B[HTMLEditorKit]
B --> C[ViewFactory]
B --> D[Parser]
D --> E[ParserCallback/Handler]
E --> F[Document]
F --> G[Views]
详细说明
JEditorPane
// 基础用法
JEditorPane editorPane = new JEditorPane();
editorPane.setContentType("text/html"); // 设置内容类型
editorPane.setText("<html><body><h1>Hello World</h1></body></html>");
// 设置编辑器
editorPane.setEditorKit(new HTMLEditorKit());
HTMLEditorKit
public class CustomHTMLEditorKit extends HTMLEditorKit {
@Override
public Document createDefaultDocument() {
HTMLDocument doc = (HTMLDocument) super.createDefaultDocument();
// 自定义文档设置
return doc;
}
@Override
public ViewFactory getViewFactory() {
return new HTMLFactory() {
@Override
public View create(Element elem) {
// 自定义视图创建
return super.create(elem);
}
};
}
}
Parser 和 Handler
基础 Parser 使用
public class CustomHTMLParser {
public static void main(String[] args) throws Exception {
String html = "<html><body><p>Hello <b>World</b></p></body></html>";
// 创建解析器
ParserDelegator parser = new ParserDelegator();
// 创建回调处理器
HTMLEditorKit.ParserCallback callback = new HTMLEditorKit.ParserCallback() {
@Override
public void handleText(char[] data, int pos) {
System.out.println("Text: " + new String(data) + " at position " + pos);
}
@Override
public void handleStartTag(HTML.Tag t,
MutableAttributeSet a,
int pos) {
System.out.println("Start tag: " + t + " at " + pos);
}
@Override
public void handleEndTag(HTML.Tag t, int pos) {
System.out.println("End tag: " + t + " at " + pos);
}
@Override
public void handleSimpleTag(HTML.Tag t,
MutableAttributeSet a,
int pos) {
System.out.println("Simple tag: " + t + " at " + pos);
}
@Override
public void handleComment(char[] data, int pos) {
System.out.println("Comment: " + new String(data));
}
@Override
public void handleEndOfLineString(String eol) {
// 处理行结束
}
};
// 执行解析
Reader reader = new StringReader(html);
parser.parse(reader, callback, true);
}
}
自定义 Document 解析器
public class CustomDocumentParser {
public static class CustomParserCallback extends HTMLEditorKit.ParserCallback {
private StringBuilder sb = new StringBuilder();
private int depth = 0;
@Override
public void handleStartTag(HTML.Tag t,
MutableAttributeSet a,
int pos) {
// 缩进显示
String indent = " ".repeat(depth);
sb.append(indent).append("<").append(t);
// 处理属性
Enumeration<?> names = a.getAttributeNames();
while (names.hasMoreElements()) {
Object name = names.nextElement();
sb.append(" ").append(name).append("='")
.append(a.getAttribute(name)).append("'");
}
sb.append(">\n");
depth++;
}
@Override
public void handleEndTag(HTML.Tag t, int pos) {
depth--;
String indent = " ".repeat(depth);
sb.append(indent).append("</").append(t).append(">\n");
}
@Override
public void handleText(char[] data, int pos) {
String indent = " ".repeat(depth);
sb.append(indent).append(new String(data)).append("\n");
}
public String getResult() {
return sb.toString();
}
}
public static void main(String[] args) throws Exception {
String html = "<html><body><div class='content'><p>Hello <b>World</b></p></div></body></html>";
ParserDelegator parser = new ParserDelegator();
CustomParserCallback callback = new CustomParserCallback();
parser.parse(new StringReader(html), callback, true);
System.out.println("Parsed HTML structure:");
System.out.println(callback.getResult());
}
}
完整的 HTML 编辑器示例
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import java.awt.*;
public class CompleteHTMLEditorExample {
private JFrame frame;
private JEditorPane editorPane;
private HTMLDocument document;
public void createAndShowGUI() {
frame = new JFrame("HTML Editor Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
// 创建编辑器
editorPane = new JEditorPane();
editorPane.setContentType("text/html");
editorPane.setEditable(true);
// 设置自定义编辑器
HTMLEditorKit kit = new HTMLEditorKit();
editorPane.setEditorKit(kit);
// 创建文档
document = (HTMLDocument) kit.createDefaultDocument();
editorPane.setDocument(document);
// 设置初始内容
String initialContent = "<html><body>" +
"<h1>HTML Editor</h1>" +
"<p>This is a <b>demo</b> of HTML editing.</p>" +
"<ul><li>Item 1</li><li>Item 2</li></ul>" +
"</body></html>";
editorPane.setText(initialContent);
// 添加滚动面板
JScrollPane scrollPane = new JScrollPane(editorPane);
frame.add(scrollPane, BorderLayout.CENTER);
// 添加工具栏
JToolBar toolbar = createToolBar();
frame.add(toolbar, BorderLayout.NORTH);
// 添加解析信息显示
JTextArea parseInfo = new JTextArea(10, 40);
parseInfo.setEditable(false);
frame.add(new JScrollPane(parseInfo), BorderLayout.SOUTH);
// 解析并显示结构
parseAndDisplayStructure();
frame.setVisible(true);
}
private JToolBar createToolBar() {
JToolBar toolbar = new JToolBar();
JButton boldBtn = new JButton("Bold");
boldBtn.addActionListener(e -> toggleBold());
toolbar.add(boldBtn);
JButton italicBtn = new JButton("Italic");
italicBtn.addActionListener(e -> toggleItalic());
toolbar.add(italicBtn);
JButton underlineBtn = new JButton("Underline");
underlineBtn.addActionListener(e -> toggleUnderline());
toolbar.add(underlineBtn);
toolbar.addSeparator();
JButton parseBtn = new JButton("Parse Structure");
parseBtn.addActionListener(e -> parseAndDisplayStructure());
toolbar.add(parseBtn);
return toolbar;
}
private void toggleBold() {
// 实现粗体切换
Action action = new StyledEditorKit.BoldAction();
action.actionPerformed(new java.awt.event.ActionEvent(
editorPane,
java.awt.event.ActionEvent.ACTION_PERFORMED,
""
));
}
private void toggleItalic() {
Action action = new StyledEditorKit.ItalicAction();
action.actionPerformed(new java.awt.event.ActionEvent(
editorPane,
java.awt.event.ActionEvent.ACTION_PERFORMED,
""
));
}
private void toggleUnderline() {
Action action = new StyledEditorKit.UnderlineAction();
action.actionPerformed(new java.awt.event.ActionEvent(
editorPane,
java.awt.event.ActionEvent.ACTION_PERFORMED,
""
));
}
private void parseAndDisplayStructure() {
try {
String html = editorPane.getText();
ParserDelegator parser = new ParserDelegator();
StringBuilder structure = new StringBuilder();
structure.append("HTML Structure:\n");
structure.append("===============\n");
parser.parse(new StringReader(html),
new HTMLEditorKit.ParserCallback() {
private int depth = 0;
@Override
public void handleStartTag(HTML.Tag t,
MutableAttributeSet a,
int pos) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) sb.append(" ");
sb.append("<").append(t);
Enumeration<?> names = a.getAttributeNames();
while (names.hasMoreElements()) {
Object name = names.nextElement();
sb.append(" ").append(name).append("='")
.append(a.getAttribute(name)).append("'");
}
sb.append(">\n");
structure.append(sb.toString());
depth++;
}
@Override
public void handleEndTag(HTML.Tag t, int pos) {
depth--;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) sb.append(" ");
sb.append("</").append(t).append(">\n");
structure.append(sb.toString());
}
@Override
public void handleText(char[] data, int pos) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) sb.append(" ");
sb.append(new String(data)).append("\n");
structure.append(sb.toString());
}
}, true);
// 获取底部的文本区域并更新
JScrollPane bottomPane = (JScrollPane) frame.getContentPane()
.getComponent(2);
JTextArea infoArea = (JTextArea) bottomPane.getViewport().getView();
infoArea.setText(structure.toString());
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new CompleteHTMLEditorExample().createAndShowGUI();
});
}
}
自定义 Parser Handler 高级示例
public class AdvancedHTMLParserHandler {
// 自定义 Tag 处理器接口
public interface TagHandler {
void handle(HTML.Tag tag, MutableAttributeSet attrs);
}
// 可配置的解析器回调
public static class ConfigurableParserCallback
extends HTMLEditorKit.ParserCallback {
private Map<HTML.Tag, TagHandler> tagHandlers = new HashMap<>();
private Map<HTML.Tag, TagHandler> endTagHandlers = new HashMap<>();
private Consumer<String> textHandler;
private StringBuffer buffer = new StringBuffer();
public void registerTagHandler(HTML.Tag tag, TagHandler handler) {
tagHandlers.put(tag, handler);
}
public void registerEndTagHandler(HTML.Tag tag, TagHandler handler) {
endTagHandlers.put(tag, handler);
}
public void setTextHandler(Consumer<String> handler) {
this.textHandler = handler;
}
@Override
public void handleStartTag(HTML.Tag t,
MutableAttributeSet a,
int pos) {
TagHandler handler = tagHandlers.get(t);
if (handler != null) {
handler.handle(t, a);
}
}
@Override
public void handleEndTag(HTML.Tag t, int pos) {
TagHandler handler = endTagHandlers.get(t);
if (handler != null) {
handler.handle(t, null);
}
}
@Override
public void handleText(char[] data, int pos) {
if (textHandler != null) {
textHandler.accept(new String(data));
}
}
}
// 使用示例
public static void main(String[] args) throws Exception {
String html = "<html><body>" +
"<h1>Title</h1>" +
"<p class='content'>Paragraph text</p>" +
"<a href='http://example.com'>Link</a>" +
"</body></html>";
ConfigurableParserCallback callback = new ConfigurableParserCallback();
// 注册处理器
callback.registerTagHandler(HTML.Tag.A, (tag, attrs) -> {
String href = (String) attrs.getAttribute(HTML.Attribute.HREF);
System.out.println("Link found: " + href);
});
callback.registerTagHandler(HTML.Tag.H1, (tag, attrs) -> {
System.out.println("Heading 1 found");
});
callback.registerTagHandler(HTML.Tag.P, (tag, attrs) -> {
String cls = (String) attrs.getAttribute(HTML.Attribute.CLASS);
System.out.println("Paragraph with class: " + cls);
});
callback.setTextHandler(text -> {
System.out.println("Text content: " + text.trim());
});
// 执行解析
ParserDelegator parser = new ParserDelegator();
parser.parse(new StringReader(html), callback, false);
}
}
- JEditorPane: 显示和编辑 HTML 的组件
- HTMLEditorKit: 提供 HTML 编辑功能的编辑器套件
- Parser: 解析 HTML 内容的解析器
- Handler/Callback: 处理解析过程中的各种事件
这些组件共同提供了完整的 HTML 处理能力,可以用于:
- HTML 内容展示
- 富文本编辑
- HTML 结构分析
- 自定义 HTML 渲染
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播