本文目录导读:

在 JEditorPane 中使用 HTMLEditorKit 实现“取消缩进”(Unindent)功能,通常需要操作文档的 段落属性,以下是几种实现方案:
使用 MutableAttributeSet 修改段落边距
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
public void unindent(JEditorPane editor) {
HTMLDocument doc = (HTMLDocument) editor.getDocument();
Element paragraph = doc.getParagraphElement(editor.getCaretPosition());
// 获取当前段落属性
AttributeSet currentAttrs = paragraph.getAttributes();
MutableAttributeSet newAttrs = new SimpleAttributeSet(currentAttrs);
// 获取当前的左缩进(CSS padding-left 或 margin-left)
int currentIndent = 0;
Object paddingLeft = currentAttrs.getAttribute(CSS.Attribute.PADDING_LEFT);
if (paddingLeft != null) {
try {
currentIndent = Integer.parseInt(paddingLeft.toString().replace("px", ""));
} catch (NumberFormatException e) {
currentIndent = 0;
}
}
// 减少缩进(每次减少20像素,最小为0)
int newIndent = Math.max(0, currentIndent - 20);
// 设置新的缩进
if (newIndent > 0) {
newAttrs.addAttribute(CSS.Attribute.PADDING_LEFT, newIndent + "px");
} else {
newAttrs.removeAttribute(CSS.Attribute.PADDING_LEFT);
}
// 应用更改
doc.setParagraphAttributes(0, doc.getLength(), newAttrs, true);
}
通过 HTML 样式标签实现
public void unindentWithStyle(JEditorPane editor) {
HTMLDocument doc = (HTMLDocument) editor.getDocument();
try {
// 获取选中文本或光标所在段落
int start = editor.getSelectionStart();
int end = editor.getSelectionEnd();
if (start == end) {
// 没有选择,操作当前段落
Element para = doc.getParagraphElement(start);
start = para.getStartOffset();
end = para.getEndOffset();
}
// 构造取消缩进的 HTML 片段
String unindentHTML = "<p style='margin-left: 0px'>";
// 这里可以使用更复杂的逻辑来处理整个段落
// 替换选中的文本
doc.replace(start, end - start, unindentHTML,
null);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
完整的缩进/取消缩进工具类
import javax.swing.text.*;
import javax.swing.text.html.*;
import java.awt.event.*;
public class IndentManager {
private static final int INDENT_STEP = 20; // 每次缩进像素
public static void indent(JEditorPane editor) {
modifyIndent(editor, INDENT_STEP);
}
public static void unindent(JEditorPane editor) {
modifyIndent(editor, -INDENT_STEP);
}
private static void modifyIndent(JEditorPane editor, int delta) {
HTMLDocument doc = (HTMLDocument) editor.getDocument();
int start = editor.getSelectionStart();
int end = editor.getSelectionEnd();
if (start == end) {
// 无选择,操作当前段落
Element para = doc.getParagraphElement(start);
start = para.getStartOffset();
end = para.getEndOffset();
}
try {
// 获取段落文本
String paragraphText = doc.getText(start, end - start);
// 计算新的缩进
int currentIndent = getCurrentIndent(doc, start);
int newIndent = Math.max(0, currentIndent + delta);
// 应用到该段落
MutableAttributeSet attrs = new SimpleAttributeSet();
if (newIndent > 0) {
attrs.addAttribute(CSS.Attribute.MARGIN_LEFT, newIndent + "px");
}
doc.setParagraphAttributes(start, end - start, attrs, false);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
private static int getCurrentIndent(HTMLDocument doc, int offset) {
Element para = doc.getParagraphElement(offset);
AttributeSet attrs = para.getAttributes();
Object marginLeft = attrs.getAttribute(CSS.Attribute.MARGIN_LEFT);
if (marginLeft != null) {
try {
return Integer.parseInt(marginLeft.toString().replace("px", ""));
} catch (NumberFormatException e) {
return 0;
}
}
return 0;
}
}
使用示例
// 在 Action 中调用
JEditorPane editor = new JEditorPane();
editor.setContentType("text/html");
editor.setText("<p>This is a test paragraph</p>");
// 绑定快捷键 Ctrl+Shift+M
editor.getInputMap().put(
KeyStroke.getKeyStroke(KeyEvent.VK_M,
InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK),
"unindent"
);
editor.getActionMap().put("unindent", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
IndentManager.unindent(editor);
}
});
注意事项
- 文档类型:确保
JEditorPane已设置为text/html类型 - 段落检测:
getParagraphElement()返回当前光标所在的段落 - 属性重置:取消缩进时要考虑移除所有缩进属性,而不仅仅是减少数值
- 性能优化:对于大文档,建议只操作选中的部分
根据你的具体需求,选择最适合的实现方式,如果需要支持列表项的缩进控制,还需要额外处理 <ul> 和 <ol> 标签的样式。