2016-08-29 4 views
0

2つのテキストフィールド(今からAとB)が、それらのいずれかのユーザー入力と同じコンテンツを共有したいと考えています。私はもう一方のミラー(BミラーA)または反対ミラー(AミラーB)を作ることができます。しかし、両方のDocumentListenerを保持すると、実行が例外をスローするようになります。JTextFieldsとDocumentListeners

OracleのDocsによると、DocumentListenerを使用してリスナー自体からドキュメントの内容を変更することはできません。最初のケース(BミラーA)またはそれとは反対のケースですでにそれを行って以来、私は奇妙な発見をしています。とにかく、コードはまだ動作しますが、2つのイベントがトリガーされるたびに例外がスローされます。

KeyListenersはこの特定のケースでは信頼できず、私はボタンの使用を拒否します。これは、DocumentListenerのリアルタイム表示が気に入っているからです。

提案がありますか?

は、ここに私のコードです:

import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 
import javax.swing.event.DocumentEvent; 
import javax.swing.event.DocumentListener; 

public class Mirror { 
    private JTextField oriText; 
    private JTextField mirrorText; 
    private static int debugCounter; //Counts the times an Event is Triggered. 

    public static void main(String[] args) { 
     Mirror gui = new Mirror(); 
     gui.build(); 
    } 

    public void build(){ 

     JFrame frame = new JFrame(); 
     JPanel panel = new JPanel(); 
     panel.setLayout(new GridBagLayout()); 
     GridBagConstraints c = new GridBagConstraints(); 
     frame.getContentPane().add(panel); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     c.gridx = 0; 
     c.gridy = 0; 
     JLabel original = new JLabel("Original"); 
     panel.add(original, c); 

     c.gridy = 1; 
     oriText = new JTextField(10); 
     panel.add(oriText,c); 


     c.gridy = 2; 
     JLabel mirror = new JLabel("Mirror"); 
     panel.add(mirror, c); 

     c.gridy = 3; 
     mirrorText = new JTextField(10); 
     panel.add(mirrorText, c);   
     mirrorText.getDocument().addDocumentListener(new MyDocumentListenerII()); // Comment this line to see only the 1st Case (B mirrors A) 
     oriText.getDocument().addDocumentListener(new MyDocumentListener()); // Comment this line to see only the 2nd Case (A mirrors B) 


     frame.pack(); 
     frame.setVisible(true); 
    } 

    class MyDocumentListener implements DocumentListener{ 

     @Override 
     public void changedUpdate(DocumentEvent e) { 
      //Does nothing. 

     } 

     @Override 
     public void insertUpdate(DocumentEvent e) { 
      mirror(); 
     } 

     @Override 
     public void removeUpdate(DocumentEvent e) { 
      mirror(); 
     } 


    } 

    class MyDocumentListenerII implements DocumentListener{ 

     @Override 
     public void changedUpdate(DocumentEvent e) { 
      // Does nothing. 
     } 

     @Override 
     public void insertUpdate(DocumentEvent e) { 
      mirror1(); 
     } 

     @Override 
     public void removeUpdate(DocumentEvent e) { 
      mirror1(); 
     } 

    } 

    public void mirror(){ 
     if (!oriText.getText().equals(mirrorText.getText())){ //Without this each Event trigger the other in some sort of Paradoxical cycle. 
      mirrorText.setText(oriText.getText()); 
      debugCounter++; 
      System.out.println(debugCounter+" events triggered"); 
     } 
    } 

    public void mirror1(){ 
     if (!mirrorText.getText().equals(oriText.getText())){ 
      oriText.setText(mirrorText.getText()); 
      debugCounter++; 
      System.out.println(debugCounter+" events triggered"); 
     } 
    } 


} 

答えて

0

問題は、どちらもJTextFieldが同期する必要があるため、各フィールドのDocumentListenerは、他のフィールドを更新する必要があるという問題があります。ただし、この更新によって、DocumentListenerが最初のフィールドを更新しようとし、DocumentListenerが実行されている間に何かがフィールドを修正しようとしているので、IllegalStateExceptionがスローされます。

解決策は、DocumentListenerがそのフィールドに対して実行されているときに、setText(String)への呼び出しをブロックすることです。これはboolean変数で行うことができます。以下DocumentListener Sのいずれかのコードは:blockAblockBbooleanインスタンスフィールド(又は方法でおそらくfinal変数)がある

textFieldA.getDocument().addDocumentListener(new DocumentListener() { 
    @Override 
    public void removeUpdate (DocumentEvent e) { 
    blockA = true; 
    if (!blockB) textFieldB.setText(textFieldA.getText()); 
    blockA = false; 
    } 
    @Override 
    public void insertUpdate (DocumentEvent e) { 
    blockA = true; 
    if (!blockB) textFieldB.setText(textFieldA.getText()); 
    blockA = false; 
    } 
    @Override 
    public void changedUpdate (DocumentEvent e) { 
    blockA = true; 
    if (!blockB) textFieldB.setText(textFieldA.getText()); 
    blockA = false; 
    } 
}); 

。ここで、メソッドがtextFieldADocumentListenerで発生すると、textFieldA.setText(String)を使用しないことを示すフラグが設定されます。 blockBが設定されている場合、textFieldB.setText(String)がブロックされている様子も見てください。 textFieldBDocumentListenerはほぼ同じです。

ここで、内のコール中にtextFieldAは設定されません。これは他のフィールドと同じです。いずれにしても、そのような呼び出しは重複します。各フィールドのテキストは、その時点で同じになります。

+0

Nailed it !!!大変ありがとうございました...私は、通常の "文書フィルタを使う"の代わりに、このような答えを得たいと考えていました。おそらくわかったように、私は法的に必要ではないとしてもテストするのが好きです。 –

0

私は、これはそれを行うには「正しい」方法です完全にわからないんだけど、私がしたすべては、各JTextFieldに同じDocumentを添付しました。

は、ここに私の初期化子から関連する部分です:

textFieldA = new JTextField(); 
textFieldA.setBounds(10, 11, 414, 20); 
textFieldA.setColumns(10); 

textFieldB = new JTextField(); 
textFieldB.setBounds(10, 42, 414, 20); 
textFieldB.setColumns(10); 
textFieldB.setDocument(textFieldA.getDocument()); 

今すぐJTextFieldの両方が同じ文書を持っているので、それらは異なることはできません。

関連する問題