2012-11-05 53 views
3

這是我第一個在學校中使用的第一個java swing應用程序。我們必須做一個凱撒編碼器。 (http://en.wikipedia.org/wiki/Caesar_cipher)使用DocumentListener修改多個JTextFields

它應該知道加密和解密,它應該自動執行,即使你不按下按鈕。 (FocusListener)

它像夢一樣工作,直到我只需要使用「代碼」就可以做到。按鈕。然後我們必須添加一個我創建的DocumentListener,如下所示。如果我僅將它用於隱藏或僅用於解密,它纔有效。發生問題時,我將兩個JTextField都添加到同一個DocumentListener中。使用「AWT-EventQueue-0」標籤獲得IllegalStateException。 它調用setText函數兩次,第二個是致命的。我認爲這是因爲如果我爲第一個JTextField鍵入一個字符它是一個插入,那麼當我用setText設置第二個JTextField的內容時,它也是一個插入。我們的教授說它可以用一面旗子很容易地修好,但我失敗了。你能幫我嗎?

Application.java

package javaswinglabor; 

    public class Application { 
     public static void main(String[] args) { 
     CaesarFrame caesarFrame = new CaesarFrame(); 
     } 
    } 

CaesarProgram.java

package javaswinglabor; 

public class CaesarProgram { 

    /** 
    * Caesar kodolo 
    * @param input 
    * @param offset 
    * @return kod 
    */ 
    static String caesarCoder(String input, char offset){ 
     input = input.toUpperCase(); 
     String kod=""; 
     for(int i=0; i < input.length(); i++){ 
     if(input.charAt(i) >= 'A' && input.charAt(i) <= 'Z') { 
      kod += (char)(65 + ((input.charAt(i) - 'A' + offset - 'A')%26)); 
     } 
     } 
     return kod; 
    } 

    /** 
    * Caesar dekodolo 
    * @param input 
    * @param offset 
    * @return kod 
    */ 
    static String caesarDecoder(String input, char offset){ 
    input = input.toUpperCase(); 
    String kod=""; 
    for(int i=0; i < input.length(); i++){ 
     if(input.charAt(i) >= 'A' && input.charAt(i) <= 'Z') { 
     kod += (char)(65 + (input.charAt(i) - offset + 26)%26); 
     } 
    } 
    return kod; 
    } 
} 

CaesarFrame.java

package javaswinglabor; 

import java.awt.FlowLayout; 
import java.awt.GridLayout; 
import java.awt.HeadlessException; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.FocusEvent; 
import java.awt.event.FocusListener; 
import javax.swing.JButton; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 
import javax.swing.text.AbstractDocument; 
import javax.swing.text.AttributeSet; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.DocumentFilter; 

public class CaesarFrame extends JFrame{ 



    //TOP JPanel 
    private JComboBox cb; 
    private JTextField t1; 
    private JButton b; 

    //DOWN JPanel 
    private JTextField t2; 

    //encrypt/decrypt 
    private boolean encrypt; 



    public CaesarFrame() throws HeadlessException { 
    super("SwingLab"); 
    this.setDefaultCloseOperation(EXIT_ON_CLOSE); 
    this.setSize(400, 110); 
    this.setResizable(true); 
    this.setLayout(new GridLayout(2, 3)); 

    JPanel pFelso = new JPanel(new FlowLayout(FlowLayout.LEFT)); 
    JPanel pAlso = new JPanel(new FlowLayout(FlowLayout.LEFT)); 
    this.add(pFelso); 
    this.add(pAlso); 

    //TOP Jpanel 
    cb = new JComboBox(fillObject()); 
    t1 = new JTextField(20); 
    b = new JButton("Code!"); 
    pFelso.add(cb); 
    pFelso.add(t1); 
    pFelso.add(b); 

    //DOWN JPanel 
    t2 = new JTextField(20); 
    //t2.setEditable(false); 
    pAlso.add(new JLabel("Output:")); 
    pAlso.add(t2); 

    //ButtonListener 
    OkButtonActionListener obl = new OkButtonActionListener(); 
    b.addActionListener(obl); 

    //DocumentListeners 
    CoderDocumentFilter cdf = new CoderDocumentFilter(); 
    DecoderDocumentFilter ddf = new DecoderDocumentFilter(); 
    ((AbstractDocument)(t1.getDocument())).setDocumentFilter((cdf)); 
    ((AbstractDocument)(t2.getDocument())).setDocumentFilter((ddf)); 

    //InputFieldKeyListener ifkl = new InputFieldKeyListener(); 
    //t1.addKeyListener(ifkl); 

    //SpecialDocumentListener t1_dl = new SpecialDocumentListener(); 
    //t1.getDocument().addDocumentListener(t1_dl); 
    //t2.getDocument().addDocumentListener(t1_dl); 

    //FocusListener 
    JTextFieldFocusListener jtfl = new JTextFieldFocusListener(); 
    t1.addFocusListener(jtfl); 
    t2.addFocusListener(jtfl); 

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



    private void Coder(){ 
    Character c = (Character)cb.getSelectedItem(); 
    t2.setText(CaesarProgram.caesarCoder(t1.getText(), c.charValue())); 
    } 
    private void Decoder(){ 
    Character c = (Character)cb.getSelectedItem(); 
    t1.setText(CaesarProgram.caesarDecoder(t2.getText(), c.charValue())); 
    } 



    private class CoderDocumentFilter extends DocumentFilter{ 
    @Override public void insertString(DocumentFilter.FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException { 
     super.insertString(fb, offset, text.toUpperCase(), attr); 
     if (encrypt) {Coder();} 
    } 
    @Override public void replace (DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attr) throws BadLocationException { 
     super.replace(fb, offset, length, text.toUpperCase(), attr); 
     if (encrypt) {Coder();} 
    } 
    @Override public void remove(DocumentFilter.FilterBypass fb, int offset, int length) throws BadLocationException{ 
     super.remove(fb, offset, length); 
     if (encrypt) {Coder();} 
    } 
    } 



    private class DecoderDocumentFilter extends DocumentFilter{ 
    @Override public void insertString(DocumentFilter.FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException { 
     super.insertString(fb, offset, text.toUpperCase(), attr); 
     if (!encrypt) {Decoder();} 
    } 
    @Override public void replace (DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attr) throws BadLocationException { 
     super.replace(fb, offset, length, text.toUpperCase(), attr); 
     if (!encrypt) {Decoder();} 
    } 
    @Override public void remove(DocumentFilter.FilterBypass fb, int offset, int length) throws BadLocationException{ 
     super.remove(fb, offset, length); 
     if (!encrypt) {Decoder();} 
    } 
    } 



    /** 
    * Egy 26-elemu Object tombot tolt fel az angol ABC nagybetuivel. 
    * @return object[] 
    */ 
    private static Object[] fillObject() { 
    Object[] object = new Object[26]; 
    for(int i=0; i < 26; i++){ 
     object[i] = (char)(i+65); 
    } 
    return object; 
    } 



    //Button listener 
    private class OkButtonActionListener implements ActionListener{ 
    @Override 
    public void actionPerformed(ActionEvent ae) { 
     if(encrypt){Coder();} 
     else{Decoder();} 
    } 
    } 



    //FocusListener 
    private class JTextFieldFocusListener implements FocusListener { 

    @Override public void focusGained(FocusEvent fe) { 
     if(t1.isFocusOwner()) {encrypt = true;} 
     else if(t2.isFocusOwner()){encrypt = false;} 
    } 

    @Override public void focusLost(FocusEvent fe) {} 
    } 



    //Previous task 
    /* 
    private class InputFieldKeyListener extends KeyAdapter { 
    @Override public void keyPressed(KeyEvent ke) { 
     super.keyPressed(ke); 
     Character c = (Character)cb.getSelectedItem(); 
     String s = String.valueOf(ke.getKeyChar()); 
     t2.setText(t2.getText() + CaesarProgram.caesarCoder(s, c.charValue())); 
    } 
    } 
    */ 
} 

我的問題解決了,謝謝大家,供大家有益的幫助。我相信它不是最優雅或最快的解決方案,但它最終能夠起作用。我會很高興,如果有人想讓它更有效率或更容易/更清潔。

+0

你真的不應該嘗試修改'DocumentListener'中的文本字段,你最好使用'DocumentFilter'。 – MadProgrammer

+0

另一個問題是,在DocumentListener中調用'setText',導致您的非法狀態,因爲文檔正在更新 – MadProgrammer

回答

3

How to Write a Document Listener

文獻聽衆不應該修改文件的內容;在聽者收到更改通知時,更改已經完成。

要解決此問題,請使用DocumentFilter而不是DocumentListener

見這個例子Implementing a Document Filter

+0

謝謝,現在很明顯,不要在DocumentListener中修改它。 (所以它只適用於日誌記錄?) 我仍然無法找出解決方案:(。我是否一直使用DoucementListener?如何解決此問題? – farkasseb

+0

不,請使用'DocumentFilter'代替。以上。 – Reimeus

+0

謝謝,我花了一些時間和谷歌,但似乎我解決了它。 – farkasseb

3

正如已經被說,你應該使用DocumentFilter,而不是試圖用DocumentListener

下面的示例修改字段說明了基本思路。我有很多的樂趣讓你的解碼/編碼方法來工作,所以我寫了我自己;)

退房MDP's Weblog一些額外的例子和Text Component Features瞭解更多信息(有關於文件過濾器一節)

public class TestCeaserCipher { 

    public static final int OFFSET = 13; 

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

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

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new CeaserCiperPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 

     }); 
    } 

    protected class CeaserCiperPane extends JPanel { 

     private JTextField encode; 
     private JTextField decode; 

     public CeaserCiperPane() { 
      encode = new JTextField(12); 
      decode = new JTextField(12); 

      setLayout(new GridBagLayout()); 
      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.gridx = 0; 
      gbc.gridy = 0; 
      gbc.fill = GridBagConstraints.HORIZONTAL; 
      gbc.weightx = 1; 
      add(encode, gbc); 
      gbc.gridy++; 
      add(decode, gbc); 

      ((AbstractDocument) encode.getDocument()).setDocumentFilter(new EncodeFilter()); 
      ((AbstractDocument) decode.getDocument()).setDocumentFilter(new DecodeFilter()); 
     } 
    } 

    public class EncodeFilter extends DocumentFilter { 
     @Override 
     public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException { 
      text = encode(text); 
      super.replace(fb, offset, length, text, attrs); 
     } 

     @Override 
     public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException { 
      text = encode(text); 
      super.insertString(fb, offset, text, attr); 

     } 
    } 

    public class DecodeFilter extends DocumentFilter { 
     @Override 
     public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException { 
      text = decode(text); 
      super.replace(fb, offset, length, text, attrs); 
     } 

     @Override 
     public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException { 
      text = decode(text); 
      super.insertString(fb, offset, text, attr); 
     } 
    } 

    public static String encode(String text) { 
     StringBuilder ciper = new StringBuilder(text.length()); 
     for (int index = 0; index < text.length(); index++) { 
      ciper.append(TestCeaserCipher.encode(text.charAt(index), OFFSET)); 
     } 

     return ciper.toString(); 
    } 

    public static String decode(String text) { 
     StringBuilder ciper = new StringBuilder(text.length()); 
     for (int index = 0; index < text.length(); index++) { 
      ciper.append(TestCeaserCipher.decdoe(text.charAt(index), OFFSET)); 
     } 

     return ciper.toString(); 
    } 

    public static char encode(char input, int offset) { 
     char encode = Character.toUpperCase(input); 
     if (encode >= 'A' && encode <= 'Z') { 

      int min = (int)'A'; 
      int max = (int)'Z'; 

      int value = (encode - offset); 

      if (value < min) { 
       value++; 
       value = min - value; 
       value = max - value; 
      } 

      encode = (char)value; 

     } 
     return encode; 
    } 

    public static char decdoe(char input, int offset) { 
     char decode = Character.toUpperCase(input); 
     if (decode >= 'A' && decode <= 'Z') { 

      int min = (int)'A'; 
      int max = (int)'Z'; 

      int value = decode + offset; 
      if (value > max) { 
       value--; 
       value = value - max; 
       value = min + value; 
      } 

      decode = (char)value; 

     } 
     return decode; 
    } 

} 
+0

哇,非常感謝@MadProgrammer,在我自己完成之後我看到了這個,所以解決方案不是你的,但是我很感謝幫助,很高興看到很多人互相幫助。 (但是我無法建立你的解決方案,有Overrides的東西,但現在我太累了,無法搜索問題。) – farkasseb