2015-10-08 86 views
0

我正在嘗試編寫一個程序,該程序將顯示兩個Jtextareas,這兩個Jtextareas都是可編輯的。目標是在編輯textAreaRom(輸入羅馬數字)時,第二個區域(textAreaArab)將顯示阿拉伯數字等值。但事情是我無法實時發生這種情況。我已閱讀了關於使用DocumentListeners的信息,但這是我第一次完成GUI編程,我不確定如何實現它。任何幫助。我是新的GUI的東西以及StackOverflow,所以很好!從另一個JtextArea實時更新一個JtextArea

注意:我的轉換方法都完美運作。

public class ArabicToRomanGUI_Hard extends JFrame 
{ 
private static final long serialVersionUID = 1L; 
private static String input = ""; 
private static String output = ""; 

//constructor to add text fields to frame 
public ArabicToRomanGUI_Hard() 
{ 
    //JFrame frame = new JFrame("Convert Back And Forth"); 
    final JTextField enterRomNumber = new JTextField(20); 
    final JTextArea textAreaRom = new JTextArea(20,20); 
    final JTextField enterArabNumber = new JTextField(20); 
    final JTextArea textAreaArab = new JTextArea(20,20); 
    setLayout(new FlowLayout()); 
    enterRomNumber.setText("Please enter a Roman numeral"); 
    enterArabNumber.setText("Please enter a Arabic Number"); 

    textAreaRom.setEditable(true); 
    textAreaArab.setEditable(true); 

    //textAreaRom.setText(enterRomNumber.getText()); 
    //textAreaArab.setText(enterArabNumber.getText()); 

    if(textAreaRom.isFocusOwner() == true) 
    { 

     textAreaRom.addKeyListener(new KeyAdapter() 
      { 
       public void keyReleased(KeyEvent e) 
       {  
        { 
         e.getKeyChar(); 
         input += e.getKeyChar(); 
         ConversionLogic_Hard.ConvertFromRomanToArabic(input); //convert 
         ConversionLogic_Hard.getCheckFail(); //check if conversion is valid. 

         output = ConversionLogic_Hard.getConvertedRomanNumeral(); //get the conversion 

         while(ConversionLogic_Hard.getCheckFail() == true && textAreaArab.isFocusOwner() == false) 
         { 
          textAreaArab.setText(output); 
         } 
         textAreaArab.setText(input); 
        } 
       } 
      });    
     } 



    getContentPane().add(enterRomNumber, BorderLayout.EAST); 
    getContentPane().add(textAreaRom, BorderLayout.WEST); 
} 

回答

0

你確實有三個問題......

  1. 更新時,首先是更新第二個文本組件,該組件是比較容易的。
  2. 當更新第二個文本組件時,更新第一個文本組件......好吧,REAL很快就會變得很複雜。
  3. 過濾輸入文本。這實際上是通過Implementing a Document Filter

相對容易的現在,真正的問題是#2,這是因爲你可以在一個骯髒的地方結束了真正的速度是第一場嘗試更新的第二場,這將觸發和事件這會導致第二個字段更新觸發的第一個字段以及導致第一個字段更新第二個字段的事件......並且您開始瞭解這個想法。

幸運的是,實際上鞦韆不會讓它壞,並會拋出一個IllegalStateException

要在走到這一步,你需要有某種方式來知道什麼時候更新到Document時被觸發由奴隸領域或當它被別的東西觸發(如setText被稱爲,用戶在字段中鍵入或粘貼文本),並忽略其中的一些事件

現在,可能有一個非常酷,簡單的方法來做這個,但今天我的大腦並不處於「簡單」模式,對不起。

於是,我開始使用自定義Document,這基本上有一個標誌,讓我檢查其狀態

public class MirrorDocument extends PlainDocument { 

    private boolean ignoreUpdates; 

    public void setIgnoreUpdates(boolean ignoreUpdates) { 
     this.ignoreUpdates = ignoreUpdates; 
    } 

    public boolean isIgnoreUpdates() { 
     return ignoreUpdates; 
    } 

} 

現在,我定義了一個DocumentListener監控更改爲Document。這DocumentListener需要它用於此偵聽更新

public static class DocumentHandler implements DocumentListener { 

    private MirrorDocument slaveDocument; 
    private boolean ignoreUpdates = false; 

    public DocumentHandler(MirrorDocument slaveDocument) { 
     this.slaveDocument = slaveDocument; 
    } 

    @Override 
    public void insertUpdate(DocumentEvent e) { 
     Document doc = e.getDocument(); 
     if (doc instanceof MirrorDocument) { 
      MirrorDocument md = (MirrorDocument) doc; 
      if (!md.isIgnoreUpdates()) { 
       try { 
        String text = e.getDocument().getText(e.getOffset(), e.getLength()); 
        slaveDocument.setIgnoreUpdates(true); 
        slaveDocument.insertString(e.getOffset(), text, null); 
       } catch (BadLocationException ex) { 
        ex.printStackTrace(); 
       } finally { 
        slaveDocument.setIgnoreUpdates(false); 
       } 
      } 
     } 
    } 

    @Override 
    public void removeUpdate(DocumentEvent e) { 
     Document doc = e.getDocument(); 
     if (doc instanceof MirrorDocument) { 
      MirrorDocument md = (MirrorDocument) doc; 
      if (!md.isIgnoreUpdates()) { 
       try { 
        slaveDocument.setIgnoreUpdates(true); 
        slaveDocument.remove(e.getOffset(), e.getLength()); 
       } catch (BadLocationException ex) { 
        ex.printStackTrace(); 
       } finally { 
        slaveDocument.setIgnoreUpdates(false); 
       } 
      } 
     } 
    } 

    @Override 
    public void changedUpdate(DocumentEvent e) { 
    } 

} 

現在,這裏真正tripy部分是圍繞ignoreUpdates國旗的「奴隸」 Document。基本上,這是什麼做的是,當一個事件發生時,我們首先檢查哪個觸發事件的DocumentignoreUpdates標誌,如果是false,我們進行設置ignoreUpdates標誌slaveDocumenttrue的,以防止它的DocumentListener處理任何新事件,然後更新slaveDocument

好吧,這可能看起來有點奇怪,我很抱歉,但相信我,這將是有道理的...(有一天......而當它,你能解釋給我送過來)

所以,接下來,我們需要創建一切,乾脆把它粘...

JTextArea left = new JTextArea(10, 20); 
    JTextArea right = new JTextArea(10, 20); 

    MirrorDocument leftDoc = new MirrorDocument(); 
    MirrorDocument rightDoc = new MirrorDocument(); 

    left.setDocument(leftDoc); 
    right.setDocument(rightDoc); 

    leftDoc.addDocumentListener(new DocumentHandler(rightDoc)); 
    rightDoc.addDocumentListener(new DocumentHandler(leftDoc)); 

所以我們創建了兩個JTextArea S,leftright 。我們創建了兩個MirrorDocument S,一個用於每個JTextArea,我們接着創建兩個DocumentHandler S,一個用於每個JTextArea並提供相對Document作爲從(rightDocleftleftDocright),這允許事件跨越並更新到發生

這使我們能夠建立類似...

MirroredTextAreas

import java.awt.EventQueue; 
import java.awt.GridLayout; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.event.DocumentEvent; 
import javax.swing.event.DocumentListener; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.Document; 
import javax.swing.text.PlainDocument; 

public class MirrorTextAreas { 

    public static void main(String[] args) { 
     new MirrorTextAreas(); 
    } 

    public MirrorTextAreas() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      JTextArea left = new JTextArea(10, 20); 
      JTextArea right = new JTextArea(10, 20); 
      setLayout(new GridLayout(1, 2)); 

      add(new JScrollPane(left)); 
      add(new JScrollPane(right)); 

      MirrorDocument leftDoc = new MirrorDocument(); 
      MirrorDocument rightDoc = new MirrorDocument(); 

      left.setDocument(leftDoc); 
      right.setDocument(rightDoc); 

      leftDoc.addDocumentListener(new DocumentHandler(rightDoc)); 
      rightDoc.addDocumentListener(new DocumentHandler(leftDoc)); 
     } 

    } 

    public class MirrorDocument extends PlainDocument { 

     private boolean ignoreUpdates; 

     public void setIgnoreUpdates(boolean ignoreUpdates) { 
      this.ignoreUpdates = ignoreUpdates; 
     } 

     public boolean isIgnoreUpdates() { 
      return ignoreUpdates; 
     } 

    } 

    public static class DocumentHandler implements DocumentListener { 

     private MirrorDocument slaveDocument; 
     private boolean ignoreUpdates = false; 

     public DocumentHandler(MirrorDocument slaveDocument) { 
      this.slaveDocument = slaveDocument; 
     } 

     @Override 
     public void insertUpdate(DocumentEvent e) { 
      Document doc = e.getDocument(); 
      if (doc instanceof MirrorDocument) { 
       MirrorDocument md = (MirrorDocument) doc; 
       if (!md.isIgnoreUpdates()) { 
        try { 
         String text = e.getDocument().getText(e.getOffset(), e.getLength()); 
         slaveDocument.setIgnoreUpdates(true); 
         slaveDocument.insertString(e.getOffset(), text, null); 
        } catch (BadLocationException ex) { 
         ex.printStackTrace(); 
        } finally { 
         slaveDocument.setIgnoreUpdates(false); 
        } 
       } 
      } 
     } 

     @Override 
     public void removeUpdate(DocumentEvent e) { 
      Document doc = e.getDocument(); 
      if (doc instanceof MirrorDocument) { 
       MirrorDocument md = (MirrorDocument) doc; 
       if (!md.isIgnoreUpdates()) { 
        try { 
         slaveDocument.setIgnoreUpdates(true); 
         slaveDocument.remove(e.getOffset(), e.getLength()); 
        } catch (BadLocationException ex) { 
         ex.printStackTrace(); 
        } finally { 
         slaveDocument.setIgnoreUpdates(false); 
        } 
       } 
      } 
     } 

     @Override 
     public void changedUpdate(DocumentEvent e) { 
     } 

    } 

} 

好了,所以這是大約一半的什麼我們需要,接下來我們需要能夠過濾被輸入到其中一個字段的內容,以便我們可以改變,這可以通過Implementing a Document Filter