我不认为这是一个新问题。但是,每当使用退格键从一直到顶部删除 JTextPane(EditorKit -> HTMLEditorKit,Document -> HTMLDocument)中的有序/无序列表时,似乎都会出现错误。下面是GlyphView的getText()方法抛出的异常。
Exception in thread "AWT-EventQueue-0" javax.swing.text.StateInvariantError: GlyphView: Stale view: javax.swing.text.BadLocationException: Invalid location
我可以为此提供 SSCCE。但模拟起来并不难。只需使用其中设置了 HTMLEditorKit 和 HTMLDOcument 模型的 JTextPane。使用自定义的“InsertOrderedList”操作或有某种方式插入字符串
<HTML><HEAD></HEAD><BODY><UL><LI></LI></UL></BODY></HTML>
这将导致在文本窗格内插入有序/无序列表。
这个错误的奇怪部分如下:
一旦你开始删除字符(如果你碰巧在项目符号列表下面有行),这些字符将被删除,直到你点击最后一个项目符号的最后一个字符。一旦达到这一点,插入符号就会拒绝向上移动,并且会抛出 GlyphView 的错误。
有时发生的情况是,在您删除了大部分字符之后 - 您仍然无法删除列表的第一个项目符号。它只会挂起,直到您执行 ctrl+a 然后退格。
我在几乎所有在线可用的基于 Java 的 HTML 编辑器中都看到了这些错误,但 JWebEngine 除外,其中不存在这种行为。不幸的是,JWebEngine 不是开源的,因此我无法查看他们的代码以了解他们是如何解决这个问题的。
我的猜测是来自 HTML 文档模型的通知有一些问题,因为光标定位代码不能正常工作。我还搜索了 Sun 错误数据库以检查是否已提出此特定问题但找不到任何问题(尽管我已经看到了很多与此非常相似的错误)。此外,我非常确定之前一定有人注意到了这一点,并且一定已经引起了 Swing 团队的注意。
使用 Swing(尤其是文本)部分的人是否知道 Sun 是否已提出此问题,或者是否已找到任何已知的解决方法来缓解该问题?
尽管用户仍然可以使用鼠标选择从窗格中删除列表,但没有使用退格键执行相同操作的选项似乎很奇怪。
SSCCE 现在已附加。重现错误请。按照附图中所示的步骤进行操作。
- 添加一行文本。然后通过单击文本窗格上方的按钮添加 2/3 项目符号。现在将插入符号放在最后一个项目符号的最后一个字符的末尾,并继续按下整个退格键,直到所有字符都被删除。
观察到的行为:最后一个子弹会挂起(不会被删除)并且会抛出异常(如上所述)
预期:没有例外,文本窗格的内容应该被清除。
public class Test {
static final JFrame frame = new JFrame ();
static final JTextPane textPane = new JTextPane ();
static EditorKit kit;
static JButton listButton;
public static void createAndShowGUI () {
//Create frame
frame.setSize(400, 600);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
//Customize text pane visual properties
textPane.setSize(300, 500);
textPane.setLocation(50, 50);
//customize text pane non visual properties
kit = new CustomEditorKit ();
textPane.setEditorKitForContentType("text/html", kit);
textPane.setContentType("text/html");
Action[] actions = ((HTMLEditorKit) kit).getActions();
Action action = null;
for (int i = 0; i < actions.length; i++) {
action = actions [i];
if (action.getValue(Action.NAME).equals("InsertUnorderedList")) {
break;
}
}
listButton = new JButton (action);
listButton.setText("List");
listButton.setSize(100, 20);
listButton.setLocation(100, 10);
listButton.setVisible(true);
/* Add button and text pane to frame */
frame.add(listButton);
frame.add(textPane);
}
public static void main(String[] args) {
try {
EventQueue.invokeAndWait(new Runnable () {
@Override
public void run() {
createAndShowGUI ();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
static class CustomEditorKit extends HTMLEditorKit {
@Override
public Document createDefaultDocument () {
return new HTMLDocument (this.getStyleSheet());
}
}
}