Вы на самом деле есть три проблемы ...
- Обновления второго компонента текста, когда первый обновляются, который, относительно легко.
- Обновление первого текстового компонента при обновлении второго ... ну, что получило REAL сложный РЕАЛЬНЫЙ быстро.
- Отфильтруйте текст так, как он был введен. Это на самом деле довольно легко, Implementing a Document Filter
Теперь реальная проблема # 2, это происходит потому, что вы могли бы в конечном итоге в неприятную место очень быстро, как первое поле пытается обновить второе поле, которое вызывает и событие который заставляет второе поле обновлять первое поле, которое запускает и событие, которое заставляет первое поле обновлять второе поле ... и вы начинаете получать идею.
К счастью, Swing фактически не позволит ему получить, что плохо, и бросить 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
берет «раб» Document
, который используется этим приемником для обновления
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
флага. В принципе, то, что это делает, когда происходит событие, сначала проверить ignoreUpdates
флаг Document
, который вызвал событие, если это false
, мы исходили установить ignoreUpdates
флаг из slaveDocument
в true
, что предотвращает его 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
с, left
и right
, Мы создаем два MirrorDocument
с, по одному для каждого JTextArea
, затем мы создаем два DocumentHandler
с, по одному для каждого JTextArea
и обеспечить противоположную Document
в качестве ведомого устройства (rightDoc
для left
и leftDoc
для right
), это позволяет случае переправиться и обновления для происходят
Это позволяет создать что-то вроде ...
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