如何在编辑另一个JTextArea时更改一个JTextArea?

时间:2014-10-16 02:12:13

标签: java jtextarea documentlistener

import javax.swing.*;
import java.awt.event.*;
import javax.swing.text.DefaultFormatter;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;


public class CipherGUI{

    public static void main(String args[]){
        try {
            UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
        } catch (Exception e) {}
        JFrame cipherGUIFrame = new CipherGUIFrame();
        cipherGUIFrame.setVisible(true);
    }
}

class CipherGUIFrame extends JFrame {

    public boolean decrypt=true;

  public CipherGUIFrame() {
    super("Caesar Cipher GUI");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(400, 600);

    JTextArea area1 = new JTextArea();
    JTextArea area2 = new JTextArea();
    JSpinner myspinner=new JSpinner();
    JPanel mainframe = new JPanel();
    JToggleButton mybutton=new JToggleButton("ENCRYPT");
    mainframe.setLayout(new BoxLayout(mainframe, BoxLayout.Y_AXIS));
    JPanel p1 = new JPanel();
    JPanel p2 = new JPanel();
    JPanel p3 = new JPanel();
    p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS));
    p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));
    p1.setBorder(BorderFactory.createTitledBorder("Cleartext"));
    p2.setBorder(BorderFactory.createTitledBorder("KEY"));
    p3.setLayout(new BoxLayout(p3, BoxLayout.X_AXIS));
    p3.setBorder(BorderFactory.createTitledBorder("Ciphertext"));
    p1.add(area1);
    p2.add(myspinner);
    p2.add(mybutton);
    p3.add(area2);
    mainframe.add(p1);
    mainframe.add(p2);
    mainframe.add(p3);
    this.add(mainframe);

    ActionListener togglelistener = new ActionListener() {
      public void actionPerformed(ActionEvent actionEvent) {
        AbstractButton abstractButton = (AbstractButton) actionEvent.getSource();
        boolean selected = abstractButton.getModel().isSelected();
        decrypt=selected;
        System.out.println("Selected (True or False?): " + selected + "\n");
      }
    };
    mybutton.addActionListener(togglelistener);


    //the following chunk of code modifies the component to update when spinner is changed automatically
    JComponent comp = myspinner.getEditor();
    JFormattedTextField field = (JFormattedTextField) comp.getComponent(0);
    DefaultFormatter formatter = (DefaultFormatter) field.getFormatter();
    formatter.setCommitsOnValidEdit(true);
    myspinner.addChangeListener(new ChangeListener() {

        @Override
        public void stateChanged(ChangeEvent e) {
            System.out.println("Key spinner changed to: " + myspinner.getValue());
        }
    });


    DocumentListener documentListener = new DocumentListener() {
      public void changedUpdate(DocumentEvent documentEvent) {
        printIt(documentEvent);
      }
      public void insertUpdate(DocumentEvent documentEvent) {
        printIt(documentEvent);
      }
      public void removeUpdate(DocumentEvent documentEvent) {
        printIt(documentEvent);
      }
      private void printIt(DocumentEvent documentEvent) {
        DocumentEvent.EventType type = documentEvent.getType();
        String typeString = null;
        if (type.equals(DocumentEvent.EventType.CHANGE)) {
          typeString = "(CHANGED KEY) ";
        }  else if (type.equals(DocumentEvent.EventType.INSERT)) {
          typeString = "(PRESSED KEY) ";
        }  else if (type.equals(DocumentEvent.EventType.REMOVE)) {
          typeString = "(DELETED KEY) ";
        }
        System.out.print("Type : " + typeString);
        Document source = documentEvent.getDocument();
        int length = source.getLength();
        System.out.println("Current size: " + length);
        String contents=source.getText(0, length);
        System.out.println(contents);
      }
    };
    area1.getDocument().addDocumentListener(documentListener);
    area2.getDocument().addDocumentListener(documentListener);
  }

  public String decipher(String istring, int key){
      String decrypted = "";

        for(int i=0; i<istring.length(); i++){

            int c = istring.charAt(i);

            if (Character.isUpperCase(c)){
                c = c - (key % 26);
                if (c < 'A')
                c = c + 26;
            }

            else if (Character.isLowerCase(c)){
                c = c - (key % 26);
                if (c < 'a')
                c = c + 26;
            }

            decrypted += (char) c;
        }

      return(decrypted);
  }

  public String encipher(String istring, int key){
      String encrypted = "";
        for(int i=0; i<istring.length(); i++){

            int c = istring.charAt(i);

            if (Character.isUpperCase(c)){
                c = c - (key % 26);
                if (c < 'A')
                c = c + 26;
            }

            else if (Character.isLowerCase(c)){
                c = c - (key % 26);
                if (c < 'a')
                c = c + 26;
            }

            encrypted += (char) c;
        }

      return (encrypted);
  }
}

这是我目前的代码。如您所见,我使用两个文本区域 - 一个用于加密,另一个用于解密。我希望一个人在其他人的更新后立即更新,反之亦然。

是我遇到问题(并在此处调试)的行
    String contents=source.getText(0, length);

线。我试图这样做,以便我可以读取文本区域的内容,只要它被更改为能够通过加密(或解密)方法发送它并将其输出到其他文本区域(我知道如何做) )。 我遇到问题的是它在更改时获取TextArea的内容。有任何想法吗? (忽略KEY CHANGED输出,那些用于测试...)

1 个答案:

答案 0 :(得分:0)

Document s不喜欢在更新时被修改,如果他们抓住你这样做就会抛出异常。

您应该使用的是DocumentFilter,它可以在将文本应用于Document之前更改文本,这是引入加密过程的好方法。

我会考虑稍微改变你的过程。而不是允许用户编辑JTextArea,只允许他们编辑第一个并使用JCheckBox来表示他们想要去哪个方向(加密/解密),这将大大简化过程...

以下示例使用DocumentFilter加密输入的文本,但使用DocumentListener,应用于area1更新Document area2,因为我们没有修改触发事件的Document,这应该是合理安全的......

Encrypt

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultFormatter;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;
import javax.swing.text.html.HTML;

public class CipherGUI {

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

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

                JFrame cipherGUIFrame = new CipherGUIFrame();
                cipherGUIFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                cipherGUIFrame.pack();
                cipherGUIFrame.setLocationRelativeTo(null);
                cipherGUIFrame.setVisible(true);
            }
        });
    }

    class CipherGUIFrame extends JFrame {

        public boolean decrypt = true;

        public CipherGUIFrame() {
            super("Caesar Cipher GUI");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setSize(400, 600);

            JTextArea area1 = new JTextArea();
            JTextArea area2 = new JTextArea();
            JSpinner myspinner = new JSpinner();
            JPanel mainframe = new JPanel();
            JToggleButton mybutton = new JToggleButton("ENCRYPT");
            mainframe.setLayout(new BoxLayout(mainframe, BoxLayout.Y_AXIS));
            JPanel p1 = new JPanel();
            JPanel p2 = new JPanel();
            JPanel p3 = new JPanel();
            p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS));
            p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));
            p1.setBorder(BorderFactory.createTitledBorder("Cleartext"));
            p2.setBorder(BorderFactory.createTitledBorder("KEY"));
            p3.setLayout(new BoxLayout(p3, BoxLayout.X_AXIS));
            p3.setBorder(BorderFactory.createTitledBorder("Ciphertext"));
            p1.add(area1);
            p2.add(myspinner);
            p2.add(mybutton);
            p3.add(area2);
            mainframe.add(p1);
            mainframe.add(p2);
            mainframe.add(p3);
            this.add(mainframe);

            ActionListener togglelistener = new ActionListener() {
                public void actionPerformed(ActionEvent actionEvent) {
                    AbstractButton abstractButton = (AbstractButton) actionEvent.getSource();
                    boolean selected = abstractButton.getModel().isSelected();
                    decrypt = selected;
                    System.out.println("Selected (True or False?): " + selected + "\n");
                }
            };
            mybutton.addActionListener(togglelistener);

            //the following chunk of code modifies the component to update when spinner is changed automatically
            JComponent comp = myspinner.getEditor();
            JFormattedTextField field = (JFormattedTextField) comp.getComponent(0);
            DefaultFormatter formatter = (DefaultFormatter) field.getFormatter();
            formatter.setCommitsOnValidEdit(true);
            myspinner.addChangeListener(new ChangeListener() {

                @Override
                public void stateChanged(ChangeEvent e) {
                    System.out.println("Key spinner changed to: " + myspinner.getValue());
                    EncryptFilter filter = (EncryptFilter) ((AbstractDocument) area2.getDocument()).getDocumentFilter();
                    filter.setKey((int)myspinner.getValue());
                    area2.setText(area1.getText());
                }
            });

            ((AbstractDocument) area2.getDocument()).setDocumentFilter(new EncryptFilter(0));

            area1.getDocument().addDocumentListener(new DocumentListener() {
                @Override
                public void insertUpdate(DocumentEvent e) {
                    try {
                        Document doc = e.getDocument();
                        String text = doc.getText(e.getOffset(), e.getLength());
                        Document encryptDoc = area2.getDocument();
                        encryptDoc.insertString(e.getOffset(), text, null);
                    } catch (BadLocationException exp) {
                        exp.printStackTrace();
                    }
                }

                @Override
                public void removeUpdate(DocumentEvent e) {
                    try {
                        Document doc = e.getDocument();
                        Document encryptDoc = area2.getDocument();
                        encryptDoc.remove(e.getOffset(), e.getLength());
                    } catch (BadLocationException exp) {
                        exp.printStackTrace();
                    }
                }

                @Override
                public void changedUpdate(DocumentEvent e) {
                    System.out.println("Changed");
                }
            });
        }
    }

    public static String decipher(String istring, int key) {
        String decrypted = "";

        for (int i = 0; i < istring.length(); i++) {

            int c = istring.charAt(i);

            if (Character.isUpperCase(c)) {
                c = c - (key % 26);
                if (c < 'A') {
                    c = c + 26;
                }
            } else if (Character.isLowerCase(c)) {
                c = c - (key % 26);
                if (c < 'a') {
                    c = c + 26;
                }
            }

            decrypted += (char) c;
        }

        return (decrypted);
    }

    public static String encipher(String istring, int key) {
        String encrypted = "";
        for (int i = 0; i < istring.length(); i++) {

            int c = istring.charAt(i);

            if (Character.isUpperCase(c)) {
                c = c - (key % 26);
                if (c < 'A') {
                    c = c + 26;
                }
            } else if (Character.isLowerCase(c)) {
                c = c - (key % 26);
                if (c < 'a') {
                    c = c + 26;
                }
            }

            encrypted += (char) c;
        }

        return (encrypted);
    }

    public class EncryptFilter extends DocumentFilter {

        private int key;

        public EncryptFilter(int key) {
            this.key = key;
        }

        public void setKey(int key) {
            this.key = key;
        }

        @Override
        public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
            System.out.println("Insert");
            text = encipher(text, key);
            super.insertString(fb, offset, text, attr);
        }

        @Override
        public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
            System.out.println("Remove");
            super.remove(fb, offset, length);
        }



        @Override
        public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {

            text = encipher(text, key);
            super.replace(fb, offset, length, text, attrs);
        }

    }
}

详细了解Implementing a Document FilterDocumentFilter Examples了解详情