trouble passing input from one JTextArea into anot

2019-09-18 15:11发布

问题:

My issue lies in my DocumentLister AreaListener. I can't seem to figure out how to pass in the text the user enters into one of the JTextAreas for my conversions and return it to the other JTextArea.

The goal of the program is to take in a user entered Roman or Arabic Number in one of the fields, convert it and return the value of the conversion to the other field in real time.

My GUI and conversion methods work, I just can't seem to wrap my head around obtaining that string from the user and printing it in real time.

public class ArabicToRomanGUI_Hard extends JFrame
{
private static final long serialVersionUID = 1L;
 JPanel panel = new JPanel();


//constructor to add text fields to frame
public ArabicToRomanGUI_Hard()
{   
    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));

    leftDoc.getDocument().addDocumentListener(AreaListener);
    rightDoc.getDocument().addDocumentListener(AreaListener);
   }



DocumentListener listener = new DocumentListener()

public class AreaListener implements DocumentListener
{
    //DocumentListener listener = new DocumentListener()

        @Override
        public void changedUpdate(DocumentEvent e) 
        {
            convertInput();
        }

        @Override
        public void insertUpdate(DocumentEvent e) 
        {
            convertInput();

        }

        @Override
        public void removeUpdate(DocumentEvent e) 
        {
            convertInput();

        }
        private void convertInput(DocumentEvent e)
        {
            boolean arabicEntered = false;
            boolean romanEntered = false; 
            for (char ch : userInputtedText.toCharArray())
            {
                if(Character.isLetter(ch))
                {
                    romanEntered = true;
                }
                if(Character.isDigit(ch))
                {
                    arabicEntered = true;
                }           
            }

            if(romanEntered = true)
            {
                if(ConversionLogic_Hard.getCheckFail() == false)
                {
                ConversionLogic_Hard.ConvertFromRomanToArabic(userInputtedText); //converts String of RomanNumerals to an arabic int
                String arabicNumberAsString = ConversionLogic_Hard.getConvertedRomanNumeral(); //converts number from int to string
                }
            }
            if(arabicEntered == true)
            {
                if(ConversionLogic_Hard.getCheckFail() == false)
                {
                ConversionLogic_Hard.ConvertFromArabicToRoman(userInputtedText); //converts String arabicNumberal to String roman numberal
                String romanNumberalAsString = ConversionLogic_Hard.getConvertedRomanNumeral(); //gets romanNumberal as String
                }
            }



        }//end convertInput


}//end AreaListener

//creates a flag to test the state of the TextArea
    public class MirrorDocument extends PlainDocument
    {
        private boolean ignoreUpdatedText;
        public void setIgnoreUpdates(boolean ignoreUpdatesText)
        {
            this.ignoreUpdatedText = ignoreUpdatesText;
        }
        public boolean isIgnoreUpdates()
        {
            return ignoreUpdatedText;
        }
    }

//when an event occurs checks the ignoreUpdatedText flag of the document to check if it is false.
//then sets the flag in the checkdocument to true to prevent the document listener from processing any new events.
//then updates the checkdocument.
public static class DocumentHandler implements DocumentListener
{
    private MirrorDocument checkDocument;
    private boolean ignoreUpdatedText = false;
    private JTextArea leftdoc, rightdoc;
    boolean arabicEntered = false;
    boolean romanEntered = false; 

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

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

    @Override
    public void changedUpdate(DocumentEvent e) 
    {
        //NOT USED  
    }

    @Override
    public void insertUpdate(DocumentEvent e) 
    {
        Document doc = e.getDocument();
        if (doc instanceof MirrorDocument)
        {
            MirrorDocument mirrordoc = (MirrorDocument) doc;
            if( !mirrordoc.isIgnoreUpdates())
            {
                try
                {
                    String textInput = e.getDocument().getText(e.getOffset(), e.getLength());
                    checkDocument.setIgnoreUpdates(true);
                    checkDocument.insertString(e.getOffset(), textInput, null);
                }
                catch(BadLocationException exc)
                {
                    exc.printStackTrace();
                }
                finally
                {
                    checkDocument.setIgnoreUpdates(false);
                }
            }
        }
    }//End insertUpdate

    }
}//class

回答1:

You can use a DocumentFilter to listen for changes.

When you create the DocumentFilter you can specify the text field to be updated with the converted text.

Using this approach you can then remove the DocumentFilter from the text field before you set its text so you avoid the recursion of two text fields trying to update one another.

The filter might look something like:

import javax.swing.*;
import javax.swing.text.*;
import java.awt.Toolkit;

public class ConversionFilter extends DocumentFilter
{
    private boolean arabic;
    private JTextField converted;

    public ConversionFilter(boolean arabic, JTextField converted)
    {
        this.arabic = arabic;
        this.converted = converted;
    }

    @Override
    public void insertString(FilterBypass fb, int offs, String str, AttributeSet a)
        throws BadLocationException
    {
        super.insertString(fb, offs, str, a);

        convertInput(fb);
    }

    @Override
    public void replace(final FilterBypass fb, final int offs, final int length, final String str, final AttributeSet a)
        throws BadLocationException
    {
        super.replace(fb, offs, length, str, a);
        convertInput(fb);
    }

    @Override
    public void remove(DocumentFilter.FilterBypass fb, int offset, int length)
        throws BadLocationException
    {
        super.remove(fb, offset, length);
        convertInput(fb);
    }

    private void convertInput(DocumentFilter.FilterBypass fb)
    {
        //  Remove the DocumentFilter from the text field to be converted

        AbstractDocument document = (AbstractDocument)converted.getDocument();
        DocumentFilter df = document.getDocumentFilter();
        document.setDocumentFilter( null );

        //  Do the conversion and update the text field

        String text = fb.getDocument().getText();
        String convertedText = arabic ? convertToRoman(text) : convertToArabic(text);
        converted.setText( convertedText );

        //  Restore the DocumentFilter on the converted text field

        document.setDocumentFilter( df );
    }
}

Then to use the filter the code might be something like:

JTextField arabicTextField = new JTextField(...);
JTextField romanTextField = new JTextField(...);

AbstractDocument arabicDocument = (AbstractDocument)arabicTextField.getDocument();
arabicDocument.setDocumentFilter( new ConversonFilter(true, romanTextField) );

AbstractDocument romanDocument = (AbstractDocument)romanTextField.getDocument();
romanDocument.setDocumentFilter( new ConversonFilter(false, arabicTextField) );

I used a DocumentFilter instead of a DocumentListener to be notified of changes to the Document simply because of the getter/setter method for the DocumentFilter make is easy to remove and restore the filter.



回答2:

Based on your previous question, https://stackoverflow.com/questions/33091530/why-doesnt-my-java-program-print-this-out, this is the DocumentFilter I came up with to work with your bi-directional editing requirements.

This code simply encodes/decodes text, but it generally doesn't matter which field your in

public class EncodeFilter extends DocumentFilter {

    private String name;
    private boolean encode;

    public EncodeFilter(String name, boolean encode) {
        this.name = name;
        this.encode = encode;
    }

    @Override
    public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
        System.out.println(name + ": Insert: " + ((MirrorDocument)fb.getDocument()).isIgnoreUpdates());
        if (((MirrorDocument)fb.getDocument()).isIgnoreUpdates()) {
            System.out.println("Encode = " + encode + " " + text);
            text = encode ? encipher(text) : decipher(text);
        }
        super.insertString(fb, offset, text, attr);
    }

    @Override
    public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
        //          System.out.println(name + ": Replace: " + ((MirrorDocument)fb.getDocument()).isIgnoreUpdates());
        if (encode) {
            text = encipher(text);
        }
        super.replace(fb, offset, length, text, attrs);
    }

    public String encipher(String istring) {
        int key = 1;
        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 String decipher(String istring) {
        String decrypted = "";
        int key = 1;
        for (int i = 0; i < istring.length(); i++) {

            int c = istring.charAt(i);

            if (Character.isUpperCase(c)) {
                c = c + (key % 26);
                if (c > 'Z') {
                    c = c - 26;
                }
            } else if (Character.isLowerCase(c)) {
                c = c + (key % 26);
                if (c > 'z') {
                    c = c - 26;
                }
            }

            decrypted += (char) c;
        }

        return (decrypted);
    }

}

And a runnable example, implemented using the previous code...

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.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;
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();

            rightDoc.setDocumentFilter(new EncodeFilter("Right", true));
            leftDoc.setDocumentFilter(new EncodeFilter("Left", false));

            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) {
        }

    }

    public class EncodeFilter extends DocumentFilter {

        private String name;
        private boolean encode;

        public EncodeFilter(String name, boolean encode) {
            this.name = name;
            this.encode = encode;
        }

        @Override
        public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
            System.out.println(name + ": Insert: " + ((MirrorDocument)fb.getDocument()).isIgnoreUpdates());
            if (((MirrorDocument)fb.getDocument()).isIgnoreUpdates()) {
                System.out.println("Encode = " + encode + " " + text);
                text = encode ? encipher(text) : decipher(text);
            }
            super.insertString(fb, offset, text, attr);
        }

        @Override
        public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
//          System.out.println(name + ": Replace: " + ((MirrorDocument)fb.getDocument()).isIgnoreUpdates());
            if (encode) {
                text = encipher(text);
            }
            super.replace(fb, offset, length, text, attrs);
        }

        public String encipher(String istring) {
            int key = 1;
            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 String decipher(String istring) {
            String decrypted = "";
            int key = 1;
            for (int i = 0; i < istring.length(); i++) {

                int c = istring.charAt(i);

                if (Character.isUpperCase(c)) {
                    c = c + (key % 26);
                    if (c > 'Z') {
                        c = c - 26;
                    }
                } else if (Character.isLowerCase(c)) {
                    c = c + (key % 26);
                    if (c > 'z') {
                        c = c - 26;
                    }
                }

                decrypted += (char) c;
            }

            return (decrypted);
        }

    }
}