我看了一遍,每个人都说,当您想要收听JTextField
或其他swing文本组件的文本更改时,请在基础文档上使用DocumentListener
。这对我没有帮助,因为我需要知道正在使用该文档的组件,并且需要对其进行操作。 DocumentEvent
知道什么文档解雇了它,但事件和文档都知道“父”组件是什么。 IIRC,这是因为给定文件可能有多个“父母”。这是我想要完成的一个例子。
JTextField txtOne = new JTextField();
JTextField txtTwo = new JTextField();
etc...
KeyListener validator = new KeyListener(){
public void updateComponent(KeyEvent e) {
//The line below CAN be accomplished with a docuement listener
//by grabbing the text of the document.
boolean valid = validationMethod(((JTextField) e.getSource()).getText());
if (valid) {
//This CANNOT be accomplished with a document listener because
//the document doesn't know what component is using it.
((JTextField) e.getSource()).setEnabled(true);
} else {
((JTextField) e.getSource()).setEnabled(false);
}
}
public void keyPressed(KeyEvent e) {updateComponent(e);}
public void keyReleased(KeyEvent e) {updateComponent(e);}
public void keyTyped(KeyEvent e) {updateComponent(e);}
};
txtOne.addKeyListener(validator);
txtTwo.addKeyListener(validator);
etc...
以上内容适用于文本更改事件来自键盘交互的情况。但是,如果我要做txtTwo.setText("asdfasdf");
,它就不会向听众发射任何东西。使用ActionListener
更糟糕,因为它只在大多数情况下按下回车键时才会触发。使用DocumentListener
至少会捕获每个文本更改,但似乎也不起作用,除非我遗漏了某些内容。
JTextField txtOne = new JTextField();
JTextField txtTwo = new JTextField();
etc...
DocumentListener validator = new DocumentListener() {
public void updateComponent(DocumentEvent e) {
boolean valid = validationMethod(e.getDocument().getText(0,
e.getDocument().getLength()));
if (valid) {
//The event has no getSource, only getDocument. The document likewise
//has no idea what the component is that is using this document.
((JTextFieldWithLabel) e.getSource()).setEnabled(true); //won't work
} else {
//no idea what i could do here....
((JTextFieldWithLabel) e.getSource()).setEnabled(false); //won't work
}
}
public void removeUpdate(DocumentEvent e) {updateComponent(e);}
public void insertUpdate(DocumentEvent e) {updateComponent(e);}
public void changedUpdate(DocumentEvent e) {updateComponent(e);}
};
txtOne.getDocument().addDocumentListener(validator);
txtTwo.getDocument().addDocumentListener(validator);
etc...
我需要共享一个监听器,因为最终会有数百个组件可能使用这个监听器及其功能。我不打算将它复制数百次,并且每个都要对特定组件进行硬编码。
答案 0 :(得分:1)
DocumentListener
你做错了。每个TextComponent
都有自己的Document
作为其数据模型。您不能将DocumentListener
添加到TextComponent,而是添加到Document
,文档事件源是Document
,而不是文本组件。
((JTextFieldWithLabel)e.getSource())。setEnabled(true); //将无效
是的,因为DocumentEvent
没有这样的功能。那么您可以使用jTextFeild.getDocument().putProperty("owner", jTextFeild);
来跟踪文档所有者的文本字段。如果您担心JTextFeild
的文档更改然后使用PropertyChangeListener
的实现"document"
和JTextComponent.setDocument()
函数一样,则会触发属性更改事件,我们需要做的就是是收听此活动并重新附加我们的DocumentListener
和"owner"
媒体资源:
class MyDocumentListener implements DocumentListener{
public void updateComponent(DocumentEvent e)
{
boolean valid = checkDataValidity(e.getDocument());
JTextField txtField = (JTextField) e.getDocument().getProperty("owner");
if(!valid)
txtField.setEnabled(false);
else txtField.setEnabled(true);
}
@Override
public void insertUpdate(DocumentEvent e) {updateComponent(e);}
@Override
public void removeUpdate(DocumentEvent e) {updateComponent(e);}
@Override
public void changedUpdate(DocumentEvent e) {}
}
class MyPropChangeListener implements PropertyChangeListener{
DocumentListener documentListenr;
public MyPropChangeListener(DocumentListener documentListener) {
this.documentListenr = documentListener;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println("chaning document!!");
JTextField txtFeild = (JTextField)evt.getSource();
txtFeild.getDocument().putProperty("owner", txtFeild);
txtFeild.getDocument().addDocumentListener(documentListenr);
}
}
//..............
MyPropChangeListener propChangeListener = new MyPropChangeListener(new MyDocumentListener());
jTextField1.addPropertyChangeListener("document", propChangeListener);
jTextField1.setDocument(new PlainDocument());
jTextField2.addPropertyChangeListener("document", propChangeListener);
jTextField2.setDocument(new PlainDocument());
虽然我建议在文本数据更改时一起使用InputVerifier
和DocumentListener
进行数据验证。 InputVerifier
有boolean verify()
进行数据验证检查。它有另一个函数shouldYieldFocus
:当它注册的组件失去焦点时调用它,只有当该方法返回true
时才转移焦点。实际上shouldYieldFocus
使用返回的boolean
verify()
函数来决定转移焦点。