我已经创建了一个覆盖JTextField
的外部类。在类中,我添加了一个DocumentListener,它可以替换防止输入某个字符。下面是代码(这不是确切的代码,为了简化这个问题):
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
class test extends JTextField{
private String filteredText;
public void getDefaultText(){
super.getText();
}
public String getText(){
return filteredText;
}
public void remword(){
super.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent arg0) {
}
@Override
public void insertUpdate(DocumentEvent arg0) {
Runnable ru = new Runnable() {
@Override
public void run() {
String finalText = getDefaultText().replace("xyz", "asd");
setText(finalText);
filteredText = finalText;
}
}
};
SwingUtilities.invokeLater(ru);
}
@Override
public void removeUpdate(DocumentEvent arg0) {
}
});
}
}
现在这段代码工作得很好,除非我使用getText()
方法返回错误Attempt to mutate in notificaton
。我试着乱搞synchronized
和Runnable
,但无济于事。
From DocumentListener
:
DocumentEvent通知是基于JavaBeans事件模型的。不能保证传递给侦听器的顺序,在对Document进行进一步修改之前必须通知所有侦听器。这意味着DocumentListener的实现可能不会改变事件的源(即关联的Document)。
您应该使用DocumentFilter
来控制文档操作。
getText()
不应该抛出这个异常。你可能指的是setText(String)
。
您不需要为这个用例创建JTextField
的子类:
((AbstractDocument) textField.getDocument()).setDocumentFilter(new DocumentFilter() {
@Override
public void insertString(DocumentFilter.FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
super.insertString(fb, offset, sanitize(string), attr);
}
@Override
public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
super.replace(fb, offset, length, sanitize(text), attrs);
}
private String sanitize(String s) {
return s == null ? null : s.replace("xyz", "asd");
}
});
注意,我的解决方案仍然允许"xyz"在文档中,如果输入字母或删除例如。"_" from "xy_z".