0

我看了一遍,每个人都说,当你想听 aJTextField或其他摆动文本组件的文本更改时,请DocumentListener在基础文档上使用 a。但这对我没有帮助,因为我需要知道正在使用文档的组件,并且需要对其采取行动。知道是什么文档触发了它,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");,它不会向那个听众发射任何东西。使用 anActionListener更糟糕,因为它只在大多数情况下按下 enter 键时触发。使用 aDocumentListener至少会捕获每个文本更改,但似乎也不起作用,除非我遗漏了什么。

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...

我需要共享一个监听器,因为最终会有数百个组件可能使用这个监听器及其功能。我不会将它复制数百次并将每个硬编码到特定组件。

4

1 回答 1

1

你在做错事DocumentListener。每个TextComponent都有自己Document的数据模型。您不能将 a 添加DocumentListener到 TextComponent 而是添加到 a Document,并且文档事件源是 a Document,而不是文本组件。

((JTextFieldWithLabel) e.getSource()).setEnabled(true); //不会工作

是的,因为没有这样的功能可用于DocumentEvent. 好吧,您可以使用它jTextFeild.getDocument().putProperty("owner", jTextFeild);来跟踪文档所有者的文本字段。如果你担心 Document 的变化,JTextFeild那么使用一个实现 PropertyChangeListenerfor "document"as with JTextComponent.setDocument()function 总是会触发一个属性更改事件,我们需要做的就是监听这个事件并将我们的DocumentListenerand"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());

虽然我建议在文本数据更改时使用InputVerifierandDocumentListener一起进行数据验证。用于数据验证检查InputVerifierboolean verify()它还有另一个函数shouldYieldFocus:当它注册的组件将失去焦点时调用它,并且只有当该方法返回时才转移焦点true。实际上 shouldYieldFocus使用函数的返回booleanverify()决定转移焦点。

于 2013-11-05T20:03:27.867 回答