4

ドキュメント リスナを JTextPane に追加しました。特定のキーワードが入力された場合に対応できるように、追加または削除されたテキストを知りたい。挿入部分は問題なく動作しますが、削除されたテキストを検出する方法がわかりません。

テキストがそこにあり、それを選択できるため、挿入は機能しますが、削除によりテキストが既に削除されているため、場所の例外が発生することがあります。

引用符で囲まれていない予約語を太字にしたいので、何が削除されたかを知る必要があります。1 文字 (引用符など) を削除すると、大きな影響が生じる可能性があります。

私のコードは次のとおりです。

    @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にあり、これは クラスであり、をAbstractDocument$DefaultDocumentEvent含みprotected Vector<UndoableEdit> edits、 タイプ の要素を 1 つ含みます。これは、このクラスでのみ使用され (他の「パッケージ」クラスはこれを取得しません)、このクラスには getter がありません。このフィールド。GapContent$RemoveUndoprotected String stringRemoveUndo

それもtoString表示されませんでした(メソッドRemoveUndoをオーバーライドしていないためtoString):

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

これは私にとって非常に奇妙で、削除された文字列を取得する簡単な方法が他にあると信じていますが、それを達成する方法がわかりません。

あなたができることの1つは、最も明白です:

    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 に答える