0

JTextField私はいろいろ調べましたが、 やその他のスイング テキスト コンポーネントのテキストの変更を聞きたいときは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ほとんどの場合、Enter キーが押されたときにのみ起動するため、を使用するとさらに悪化します。a を使用する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...

リスナーを共有する必要があるのは、最終的に、このリスナーとその関数を潜在的に使用できるコンポーネントが何百もあるからです。何百回もコピーパスタして、それぞれを特定のコンポーネントにハードコーディングするつもりはありません。

4

1 に答える 1

1

あなたは間違ったことをしていDocumentListenerます。それぞれTextComponentが独自Documentのデータ モデルを持っています。DocumentListenerを TextComponent に追加することはできませんがDocument、ドキュメント イベント ソースはDocumentであり、テキスト コンポーネントではありません。

((JTextFieldWithLabel) e.getSource()).setEnabled(true); //動作しません

はい、 で利用できるそのような機能がないためですDocumentEventjTextFeild.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());

テキストデータの変更時にデータ検証のためにInputVerifierand を一緒に使用することをお勧めしますが。データ検証チェック用に持っています。これには別の関数があります。これは、登録されているコンポーネントがフォーカスを失うときに呼び出され、そのメソッドが返された場合にのみフォーカスが転送されます。関数の戻り値を実際 に使用して、フォーカスの移動に関する決定を下します。DocumentListenerInputVerifierboolean verify()shouldYieldFocustrueshouldYieldFocusbooleanverify()

于 2013-11-05T20:03:27.867 に答える