将输入从一个 JTextArea 传递到另一个 JTextArea 时遇到问题
trouble passing input from one JTextArea into another JTextArea
我的问题出在我的 DocumentLister AreaListener 上。我似乎无法弄清楚如何将用户输入的文本传递到 JTextAreas 之一以进行转换,然后 return 将其传递到另一个 JTextArea。
该程序的目标是接收用户在其中一个字段中输入的罗马数字或阿拉伯数字,将其转换并将 return 实时转换到另一个字段的值。
我的 GUI 和转换方法有效,但我似乎无法集中精力从用户那里获取该字符串并实时打印它。
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
您可以使用 DocumentFilter
来监听变化。
创建 DocumentFilter
时,您可以指定要用转换后的文本更新的文本字段。
使用这种方法,您可以在设置文本之前从文本字段中删除 DocumentFilter
,这样就可以避免两个文本字段试图相互更新的递归。
过滤器可能类似于:
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 );
}
}
然后要使用过滤器,代码可能类似于:
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) );
我使用 DocumentFilter 而不是 DocumentListener 来通知文档的更改,仅仅是因为 DocumentFilter 的 getter/setter 方法很容易删除和恢复过滤器。
根据您之前的问题,,这是我想出的 DocumentFilter
来满足您的双向编辑要求。
此代码只是 encodes/decodes 文本,但通常您在哪个字段中并不重要
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);
}
}
以及一个可运行的示例,使用之前的代码实现...
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);
}
}
}
我的问题出在我的 DocumentLister AreaListener 上。我似乎无法弄清楚如何将用户输入的文本传递到 JTextAreas 之一以进行转换,然后 return 将其传递到另一个 JTextArea。
该程序的目标是接收用户在其中一个字段中输入的罗马数字或阿拉伯数字,将其转换并将 return 实时转换到另一个字段的值。
我的 GUI 和转换方法有效,但我似乎无法集中精力从用户那里获取该字符串并实时打印它。
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
您可以使用 DocumentFilter
来监听变化。
创建 DocumentFilter
时,您可以指定要用转换后的文本更新的文本字段。
使用这种方法,您可以在设置文本之前从文本字段中删除 DocumentFilter
,这样就可以避免两个文本字段试图相互更新的递归。
过滤器可能类似于:
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 );
}
}
然后要使用过滤器,代码可能类似于:
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) );
我使用 DocumentFilter 而不是 DocumentListener 来通知文档的更改,仅仅是因为 DocumentFilter 的 getter/setter 方法很容易删除和恢复过滤器。
根据您之前的问题,,这是我想出的 DocumentFilter
来满足您的双向编辑要求。
此代码只是 encodes/decodes 文本,但通常您在哪个字段中并不重要
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);
}
}
以及一个可运行的示例,使用之前的代码实现...
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);
}
}
}