我已将文档侦听器添加到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);
}
答案 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方法,则会得到之前的文本。