Swing HTMLEditorKit / JEditorPane 不能正确处理 <br> 和空行
Swing HTMLEditorKit / JEditorPane doesn't handle <br> and empty lines correctly
当由 HTMLEditorKit 支持的 JEditorPane 包含一个 <br>
标记后跟一个空行时,该行未正确呈现且插入符号未正确处理。考虑这个示例代码:
import java.awt.*;
import java.io.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
public class HTMLEditorTest {
public static void main(String[] args) throws IOException, BadLocationException {
JFrame frame = new JFrame();
Reader stringReader = new StringReader("test<br><p>a");
HTMLEditorKit htmlKit = new HTMLEditorKit();
HTMLDocument htmlDoc = (HTMLDocument) htmlKit.createDefaultDocument();
htmlKit.read(stringReader, htmlDoc, 0);
JEditorPane editorPane = new JEditorPane();
editorPane.setEditorKit(htmlKit);
editorPane.setDocument(htmlDoc);
frame.getContentPane().add(BorderLayout.CENTER, new JScrollPane(editorPane));
frame.setBounds(100, 100, 500, 400);
frame.setVisible(true);
}
}
<br>
标签后的空行不渲染。当插入符号位于 'a' 字符左侧并按下向上箭头键时,插入符号消失:
在按下'up'之前:
按下'up'后:
注意'test'和'a'之间的距离太小了,插入符号消失了。
当您随后输入文本时,缺失的空行变为可见:
问题似乎是空行以 0 像素的高度呈现,因此不可见,包括插入符(如果它在该行上)。一旦该行有内容,该内容就会强制使用非零行高。
您是否知道针对此问题的简单解决方法/修复方法?我估计在最坏的情况下,我必须写我的 own editor kit (see also here and here for custom line wrapping in JEditorPane) and/or custom tag (also here).
找到解决方案,使用自定义编辑器工具包:
public class MyEditorKit extends HTMLEditorKit {
private static final int MIN_HEIGHT_VIEWS = 10;
@Override
public ViewFactory getViewFactory() {
return new HTMLFactory() {
@Override
public View create(Element e) {
View v = super.create(e);
// Test for BRView must use String comparison, as the class is package-visible and not available to us
if ((v instanceof InlineView) && !v.getClass().getSimpleName().equals("BRView")) {
View v2 = new InlineView(e) {
@Override
public float getMaximumSpan(int axis) {
float result = super.getMaximumSpan(axis);
if (axis == Y_AXIS) {
result = Math.max(result, MIN_HEIGHT_VIEWS);
}
return result;
}
@Override
public float getMinimumSpan(int axis) {
float result = super.getMinimumSpan(axis);
if (axis == Y_AXIS) {
result = Math.max(result, MIN_HEIGHT_VIEWS);
}
return result;
}
@Override
public float getPreferredSpan(int axis) {
float result = super.getPreferredSpan(axis);
if (axis == Y_AXIS) {
result= Math.max(result, MIN_HEIGHT_VIEWS);
}
return result;
}
};
v = v2;
}
return v;
}
};
}
}
编辑器工具包 returns 自定义 HTML 工厂。该工厂为叶元素创建自定义 InlineView 对象,其中 InlineView 的高度不能为 0。它总是至少有一个 MIN_HEIGHT_VIEW,我将其设置为 10 像素(在默认字体大小下工作得相当好)。当渲染 HTML 只是为了查看时,原始实现是有意义的,因为确实应该忽略 <br>
标记后的空行。但是对于编辑,用户希望在插入换行符后在下一行看到插入符号。
当由 HTMLEditorKit 支持的 JEditorPane 包含一个 <br>
标记后跟一个空行时,该行未正确呈现且插入符号未正确处理。考虑这个示例代码:
import java.awt.*;
import java.io.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
public class HTMLEditorTest {
public static void main(String[] args) throws IOException, BadLocationException {
JFrame frame = new JFrame();
Reader stringReader = new StringReader("test<br><p>a");
HTMLEditorKit htmlKit = new HTMLEditorKit();
HTMLDocument htmlDoc = (HTMLDocument) htmlKit.createDefaultDocument();
htmlKit.read(stringReader, htmlDoc, 0);
JEditorPane editorPane = new JEditorPane();
editorPane.setEditorKit(htmlKit);
editorPane.setDocument(htmlDoc);
frame.getContentPane().add(BorderLayout.CENTER, new JScrollPane(editorPane));
frame.setBounds(100, 100, 500, 400);
frame.setVisible(true);
}
}
<br>
标签后的空行不渲染。当插入符号位于 'a' 字符左侧并按下向上箭头键时,插入符号消失:
在按下'up'之前:
按下'up'后:
注意'test'和'a'之间的距离太小了,插入符号消失了。
当您随后输入文本时,缺失的空行变为可见:
问题似乎是空行以 0 像素的高度呈现,因此不可见,包括插入符(如果它在该行上)。一旦该行有内容,该内容就会强制使用非零行高。
您是否知道针对此问题的简单解决方法/修复方法?我估计在最坏的情况下,我必须写我的 own editor kit (see also here and here for custom line wrapping in JEditorPane) and/or custom tag (also here).
找到解决方案,使用自定义编辑器工具包:
public class MyEditorKit extends HTMLEditorKit {
private static final int MIN_HEIGHT_VIEWS = 10;
@Override
public ViewFactory getViewFactory() {
return new HTMLFactory() {
@Override
public View create(Element e) {
View v = super.create(e);
// Test for BRView must use String comparison, as the class is package-visible and not available to us
if ((v instanceof InlineView) && !v.getClass().getSimpleName().equals("BRView")) {
View v2 = new InlineView(e) {
@Override
public float getMaximumSpan(int axis) {
float result = super.getMaximumSpan(axis);
if (axis == Y_AXIS) {
result = Math.max(result, MIN_HEIGHT_VIEWS);
}
return result;
}
@Override
public float getMinimumSpan(int axis) {
float result = super.getMinimumSpan(axis);
if (axis == Y_AXIS) {
result = Math.max(result, MIN_HEIGHT_VIEWS);
}
return result;
}
@Override
public float getPreferredSpan(int axis) {
float result = super.getPreferredSpan(axis);
if (axis == Y_AXIS) {
result= Math.max(result, MIN_HEIGHT_VIEWS);
}
return result;
}
};
v = v2;
}
return v;
}
};
}
}
编辑器工具包 returns 自定义 HTML 工厂。该工厂为叶元素创建自定义 InlineView 对象,其中 InlineView 的高度不能为 0。它总是至少有一个 MIN_HEIGHT_VIEW,我将其设置为 10 像素(在默认字体大小下工作得相当好)。当渲染 HTML 只是为了查看时,原始实现是有意义的,因为确实应该忽略 <br>
标记后的空行。但是对于编辑,用户希望在插入换行符后在下一行看到插入符号。