如何知道从JTextPane中删除了哪些文本

时间:2012-07-27 20:21:37

标签: swing

我已将文档侦听器添加到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);
}

2 个答案:

答案 0 :(得分:4)

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

我已经为此查看了Swing库的源代码。当然 - DocumentEvent中的这些信息属于AbstractDocument$DefaultDocumentEvent类,其中包含protected Vector<UndoableEdit> edits,其中包含GapContent$RemoveUndo类型的一个元素,其中包含protected 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;
}

答案 1 :(得分:2)

我遇到了和你相同的问题。 Xeon解释的东西也帮助了我很多。但之后,我找到了一种方法。在我的例子中,我创建了一个自定义的StyledDocument类,它扩展了DefaultStyledDocument:

   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方法,则会得到之前的文本。