4

我已向 JTextPane 添加了一个文档侦听器。我想知道添加或删除了哪些文本,以便在输入某些关键词时采取行动。插入部分工作得很好,但我不知道如何检测删除了哪些文本。

插入有效,因为文本在那里并且我可以选择它,但是删除已经删除了文本,所以有时我会遇到错误的位置异常。

我想将不在引号内的保留字加粗,因此我需要知道已删除的内容,即使删除一个字符(如引号)也会产生巨大影响。

我的代码如下:

    @Override
public void insertUpdate(DocumentEvent e)
{
    Document doc = e.getDocument();
    String i = ""; 

    try
    {
        i = doc.getText(e.getOffset(), e.getLength());
    }
    catch(BadLocationException e1)
    {
        e1.printStackTrace();
    }

    System.out.println("INSERT:" + e + ":" + i);
}

@Override
public void removeUpdate(DocumentEvent e)
{
    Document doc = e.getDocument();
    String i = ""; 

    try
    {
        i = doc.getText(e.getOffset(), e.getLength());
    }
    catch(BadLocationException e1)
    {
        e1.printStackTrace();
    }

    System.out.println("REMOVE:" + e + ":" + i);
}
4

2 回答 2

4

奇怪的是,没有简单的方法来获取这些信息。

为此,我查看了 Swing 库的源代码。当然 - 中有这个信息DocumentEvent,它属于 class AbstractDocument$DefaultDocumentEvent,其中 contains protected Vector<UndoableEdit> edits,其中包含一个 type 元素GapContent$RemoveUndo,其中 containsprotected String string仅在这个类中使用(没有其他“包”类得到这个)并且这个RemoveUndo类没有 getter这个领域。

甚至toString没有显示它(因为RemoveUndo没有覆盖toString方法):

[javax.swing.text.GapContent$RemoveUndo@6303ddfd hasBeenDone: true alive: true]

这对我来说太奇怪了,我相信还有其他一些简单的方法可以获取删除的字符串,而我只是不知道如何完成它。

您可以做的一件事是最明显的:

    final JTextArea textArea = new JTextArea();
    textArea.addKeyListener(new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {
            previousText = textArea.getText();
        }
    });

    textArea.getDocument().addDocumentListener(new DocumentListener() {
        @Override
        public void removeUpdate(DocumentEvent e) {
            if(previousText != null) {
                String removedStr = previousText.substring(e.getOffset(), e.getOffset() + e.getLength());
                System.out.println(removedStr);
            }
        }
        @Override
        public void insertUpdate(DocumentEvent e) {
        }
        @Override
        public void changedUpdate(DocumentEvent e) {
        }
    });

其中previousText是一个实例变量。

或(有史以来最讨厌的):

textArea.getDocument().addDocumentListener(new DocumentListener() {
        @Override
        public void removeUpdate(DocumentEvent e) {
            String removedString = getRemovedString(e);
            System.out.println(removedString);
        }

        @Override
        public void insertUpdate(DocumentEvent e) {
        }

        @Override
        public void changedUpdate(DocumentEvent e) {
        }
    });

加上这个方法:

public static String getRemovedString(DocumentEvent e) {
    try {
        Field editsField = null;
        Field[] fields = CompoundEdit.class.getDeclaredFields();
        for(Field f : fields) {
            if(f.getName().equals("edits")) {
                editsField = f;
                break;
            }
        }
        editsField.setAccessible(true);
        List edits = (List) editsField.get(e);
        if(edits.size() != 1) {
            return null;
        }

        Class<?> removeUndo = null;
        for(Class<?> c : GapContent.class.getDeclaredClasses()) {
            if(c.getSimpleName().equals("RemoveUndo")) {
                removeUndo = c;
                break;
            }
        }

        Object removeUndoInstance = edits.get(0);
        fields = removeUndo.getDeclaredFields();

        Field stringField = null;
        for(Field f : fields) {
            if(f.getName().equals("string")) {
                stringField = f;
                break;
            }
        }

        stringField.setAccessible(true);
        return (String) stringField.get(removeUndoInstance);
    }
    catch(SecurityException e1) {
        e1.printStackTrace();
    }
    catch(IllegalArgumentException e1) {
        e1.printStackTrace();
    }
    catch(IllegalAccessException e1) {
        e1.printStackTrace();
    }
    return null;
}
于 2012-07-27T21:48:42.047 回答
2

我和你有同样的问题。Xeon 的解释也对我有很大帮助。但之后,我找到了一种方法来做到这一点。就我而言,我创建了一个扩展 DefaultStyledDocument 的自定义 StyledDocument 类:

   public class CustomStyledDocument extends DefaultStyledDocument
    {


        public CustomStyledDocument () {
           super();
    }

     @Override
        public void insertString(int offset, String string, AttributeSet as) throws BadLocationException {
            super.insertString(offset, string, as);
    }

    @Override
        public void remove(int offset, int i1) throws BadLocationException { 
        String previousText = getText(offset, i1);
        super.remove(offset, i1);
    }

}

所以如果你在调用 super.remove(...) 之前调用 getText 方法,你会得到之前的文本。

于 2013-07-31T16:43:26.993 回答